<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wikigeii.iut-troyes.univ-reims.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fredmn</id>
	<title>troyesGEII - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://wikigeii.iut-troyes.univ-reims.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fredmn"/>
	<link rel="alternate" type="text/html" href="https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Sp%C3%A9cial:Contributions/Fredmn"/>
	<updated>2026-09-20T13:36:11Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:PooTD2_barregraphe&amp;diff=21142</id>
		<title>Cours:PooTD2 barregraphe</title>
		<link rel="alternate" type="text/html" href="https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:PooTD2_barregraphe&amp;diff=21142"/>
		<updated>2026-09-14T08:23:53Z</updated>

		<summary type="html">&lt;p&gt;Fredmn : /* 74HC138 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
=schéma=&lt;br /&gt;
[[Image:CarteBarregraphe.png|500px|droite]]&lt;br /&gt;
*[[Media:CarteLeds.pdf]]&lt;br /&gt;
&lt;br /&gt;
=74HC138=&lt;br /&gt;
&lt;br /&gt;
la carte utilise un démultiplexeur [[Media:Sn74hc138.pdf|74HC138]] pour commander l&#039;état de 8 leds.&lt;br /&gt;
&lt;br /&gt;
*description&lt;br /&gt;
**on choisit le numéro de la led avec un nombre sur 3 bits ( CBA )&lt;br /&gt;
**si l&#039;entrée Enable est à 0, toutes les leds sont éteintes&lt;br /&gt;
**Attention : il faut forcer un peu les connecteurs (détrompeurs devant) ET contrôler que la nappe n&#039;est pas croisée&lt;br /&gt;
*signaux sur les connecteurs&lt;br /&gt;
**le connecteur CN2 :&lt;br /&gt;
***En&lt;br /&gt;
***C : bit de poids fort du nombre&lt;br /&gt;
**le connecteur CN1&lt;br /&gt;
***B&lt;br /&gt;
***A : bit de poids faible du nombre&lt;br /&gt;
*Exemple : pour allumer la led 5 ( 101 en binaire), il faut&lt;br /&gt;
**En à 1&lt;br /&gt;
**C à 1&lt;br /&gt;
**B à 0&lt;br /&gt;
**A à 1&lt;br /&gt;
&lt;br /&gt;
=création d&#039;une classe Barregraphe=&lt;br /&gt;
*constructeur avec 4 paramètres (dans l&#039;ordre le numéro de GPIO de En,C,B,A)&lt;br /&gt;
*attributs :&lt;br /&gt;
**numGpioEn&lt;br /&gt;
**numGpioC&lt;br /&gt;
**numGpioB&lt;br /&gt;
**numGpioA&lt;br /&gt;
*méthode&lt;br /&gt;
**allumerLedNumero(int numero)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Question|Ecrire le programme et vérifier le fonctionnement}}&lt;br /&gt;
&lt;br /&gt;
=ajout de fonctionnalités (méthodes)=&lt;br /&gt;
&lt;br /&gt;
*ajouter des méthodes (et attribut si besoin)&lt;br /&gt;
**allumerLedSuivante()&lt;br /&gt;
**allumerLedPrecedente()&lt;br /&gt;
&lt;br /&gt;
{{Question|utiliser 2 boutons pour :}}&lt;br /&gt;
*si le bouton 1 est appuyé, on passe à la led suivante toutes les 250ms&lt;br /&gt;
*si le bouton 2 est appuyé, on passe à la led précédente toutes les 250ms&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:Elen4_TNS&amp;diff=21141</id>
		<title>Cours:Elen4 TNS</title>
		<link rel="alternate" type="text/html" href="https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:Elen4_TNS&amp;diff=21141"/>
		<updated>2026-09-10T05:23:09Z</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;
&#039;&#039;&#039;&amp;lt;big&amp;gt;S4 - ESE - Traitement numérique du signal&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;1,5h&lt;br /&gt;
* TD : 6 séances d&#039;1,5h + une évaluation d&#039;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). Gnuradio est disponible en local sur les ordinateurs, mais aussi directement en ligne : https://gnuradioworld.com/&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&#039;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&#039;utilisateur (pas d&#039;utilisation d&#039;é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&#039;un fichier &amp;lt;/code&amp;gt;pixi.lock&amp;lt;/code&amp;gt; contenant description complète et déterministe de l&#039;environnement installé.&lt;br /&gt;
&lt;br /&gt;
Voici un guide :&lt;br /&gt;
# Installer pixi, en suivant l&#039;indication décrite dans https://pixi.prefix.dev/latest/installation/&amp;lt;br/&amp;gt;&#039;&#039;Note : l&#039;installation est locale à l&#039;utilisateur, elle ne sera nécessaire qu&#039;une seule fois pour le semestre&#039;&#039;&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; &#039;&#039;Incidemment, ces dépendances nécessitent python qui sera installé automatiquement (à l&#039;aide du dépot conda). Vous pouvez afficher le fichier pixi.toml pour observer ces dépendances.&#039;&#039;&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&#039;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;
&#039;&#039;&#039;Important&#039;&#039;&#039; :&lt;br /&gt;
* Il n&#039;est normalement pas nécessaire d&#039;éditer le fichier &amp;lt;code&amp;gt;pixi.toml&amp;lt;/code&amp;gt;&lt;br /&gt;
* Il n&#039;est &#039;&#039;&#039;jamais&#039;&#039;&#039; nécessaire d&#039;é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>https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:InfoS3_POO&amp;diff=21139</id>
		<title>Cours:InfoS3 POO</title>
		<link rel="alternate" type="text/html" href="https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:InfoS3_POO&amp;diff=21139"/>
		<updated>2026-09-07T07:37:34Z</updated>

		<summary type="html">&lt;p&gt;Fredmn : /* Pratique */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Pratique =&lt;br /&gt;
&lt;br /&gt;
Attention : nous utilisons Qt5 au département.&lt;br /&gt;
&lt;br /&gt;
* Pour installer QT Creator (ainsi que C++ et Qt) sous de nombreux OS : suivre ce tutoriel &lt;br /&gt;
 https://guillaumebelz.github.io/&lt;br /&gt;
&lt;br /&gt;
* Guide d&#039;installation de Qt par Geoffrey Lecoq (merci à lui) : [[Fichier:GuideQT_Lecoq.pdf]]&lt;br /&gt;
&lt;br /&gt;
= Évaluations = &lt;br /&gt;
&lt;br /&gt;
*[[Cours:DevoirPOOcpp2|Évaluation n°1]]&lt;br /&gt;
*[[Cours:DevoirMaisonPOO1|Devoir maison n°1]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*[[Cours:DevoirPOO1|Évaluation n°1]]--&amp;gt;&lt;br /&gt;
*[[Cours:DevoirPOO2Ressources|Évaluation n°2 ressources]]&lt;br /&gt;
*[[Cours:DevoirPOO2|Évaluation n°2 sujet]]&lt;br /&gt;
&lt;br /&gt;
= Cours magistral =&lt;br /&gt;
&lt;br /&gt;
== Diapositives et support de cours ==&lt;br /&gt;
&lt;br /&gt;
* Diapositives de la partie Introduction : [[Media:POOintro.pdf]]&lt;br /&gt;
* Diapositives de la partie Notions : [[Media:POOnotions.pdf]]&lt;br /&gt;
* Diapositives de la partie Approfondissements : [[Media:POOapprofondissements.pdf]]&lt;br /&gt;
* Support de cours imprimable : [[Media:POOsupport.pdf]]&lt;br /&gt;
&lt;br /&gt;
== Projets de démonstration de CM ==&lt;br /&gt;
&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;minimal&amp;lt;/code&amp;gt; : [[Media:minimal.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;simpleNonOOCar&amp;lt;/code&amp;gt; : [[Media:simpleNonOOCar.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;simpleOOCar&amp;lt;/code&amp;gt; : [[Media:simpleOOCar.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;twoOOCars&amp;lt;/code&amp;gt; : [[Media:twoOOCars.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes_start&amp;lt;/code&amp;gt; : [[Media:formes_start.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes&amp;lt;/code&amp;gt; : [[Media:formes.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes_nonpolymorphes&amp;lt;/code&amp;gt; [[Media:formes_nonpolymorphes.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes_polymorphes&amp;lt;/code&amp;gt; [[Media:formes_polymorphes.zip]]&lt;br /&gt;
&lt;br /&gt;
== Lectures externes potentiellement utiles ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Cours de POO d&#039;openclassrooms&#039;&#039;&#039; :&lt;br /&gt;
&lt;br /&gt;
1. [https://openclassrooms.com/fr/courses/7137751-programmez-en-oriente-objet-avec-c/7673331-decouvrez-la-notion-de-poo Découvrez La notion de programmation orientée objet (POO)]&lt;br /&gt;
&lt;br /&gt;
2. [https://openclassrooms.com/fr/courses/7137751-programmez-en-oriente-objet-avec-c Programmez en orienté objet avec C++]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Les pointeurs et leur utilisation avec des objets&#039;&#039;&#039; :&lt;br /&gt;
&lt;br /&gt;
1. [https://openclassrooms.com/fr/courses/1894236-apprenez-a-programmer-en-c/7534366-declarez-les-pointeurs Déclarez les pointeurs]&lt;br /&gt;
&lt;br /&gt;
2. [https://openclassrooms.com/fr/courses/7137751-programmez-en-oriente-objet-avec-c/7531356-associez-les-classes-et-les-pointeurs Associez les classes et les pointeurs] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- [[media:POO-Support.pdf|Support de cours en pdf (à télécharger)]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Séances : C++ sous QT Creator =&lt;br /&gt;
&lt;br /&gt;
*[[Cours:pooTD1_ledsbps|séance 1 (4,5h) : découverte du C++ et de QT Creator]]&lt;br /&gt;
*[[Cours:pooTD2_barregraphe|séance 2 (1,5h) : Écriture d&#039;une classe (Barregraphe)]]&lt;br /&gt;
* séance 3 (1h) : Évaluation&lt;br /&gt;
*[[Cours:interfaceQT|séance 3 (1,5h) : 1ère interface graphique]]&lt;br /&gt;
*[[Cours:signalSlotQT|séance 4 (3h)  : classe avec slot et émission de signal]]&lt;br /&gt;
*[[Cours:TPheritageIO|séance 5 (3h): on hérite ! (pi4)]]&lt;br /&gt;
*[[Cours:pointeursCpp|séance 6 (1,5h) : manipulation de pointeurs/références]]&lt;br /&gt;
*[[Cours:DiyWidgetQT|séance 7 (3h) : création d&#039;un widget DIY]] (à déplacer pour utilisation dans le DM)&lt;br /&gt;
*[[Cours:TPqtFNS|séance 8 (1,5h) : Machine à état fini]]&lt;br /&gt;
*[[Cours:pooSignal|séance 9 (0,5h) : Emission de signal]]&lt;br /&gt;
*[[Cours:qtTCP|séance 10 (1,5h) : Révisions ou communication entre 2 cartes par TCP]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Archives==&lt;br /&gt;
*[[Cours:pooTD2_classes|séance 2 (3h) : création de classes et manipulation d&#039;objets]]&lt;br /&gt;
*{{Rouge|Evaluation (1,5h)}}&lt;br /&gt;
*[[Cours:interfaceQT|séance 3 (1,5h) : 1ère interface graphique]]&lt;br /&gt;
*[[Cours:signalSlotQT|séance 4 (1.5h)  : classe avec slot et émission de signal]]&lt;br /&gt;
*[[Cours:TPgpioQT|séance 5 (3h) : GPIO (pi4) ]]&lt;br /&gt;
*[[Cours:TPheritageIO|séance 6 (4,5h): on hérite ! (pi4)]]&lt;br /&gt;
*[[Cours:HeritageWidgetQT|séance 7 (1,5h) : spécialisation de Widgets]]&lt;br /&gt;
*[[Cours:TPqtFNS|séance 8 (3h) : Machine à état fini (&amp;quot;pi4&amp;quot;) ]]&lt;br /&gt;
*[[Cours:pointeursCpp|séance 9 (1,5h) : manipulation de pointeurs/références]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*{{Rouge|Evaluation (3h) (pi4)}}&lt;br /&gt;
&lt;br /&gt;
=Pour aller plus loin=&lt;br /&gt;
*[[Cours:diyWidgetQT|Créer son widget]]&lt;br /&gt;
*[[Cours:TPgpioControleur|Tp 2 : contrôleur de lampes]]&lt;br /&gt;
*[[Cours:gitQtCreator|Utilisation de git avec qt creator]]&lt;br /&gt;
&lt;br /&gt;
=Ressources=&lt;br /&gt;
*https://www.kdab.com/wp-content/uploads/stories/slides/DD13/dd13_signalsslots.pdf&lt;br /&gt;
&lt;br /&gt;
=Logiciel=&lt;br /&gt;
==Vm Qt Creator==&lt;br /&gt;
&lt;br /&gt;
Vous pouvez utiliser l&#039;image VirtualBox suivante sur laquelle QtCreator est installé&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1BdVNnAtpYM14ztf215gBVx5b2P8iAAix/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le mot de passe est geii&lt;br /&gt;
&lt;br /&gt;
==Simulation de gpio==&lt;br /&gt;
&lt;br /&gt;
*simulateur leds/bp/interrupteur&lt;br /&gt;
**dans la machine virtuelle VirtualBox&lt;br /&gt;
**au besoin supprimer le fichier GpioSimulateur.zip dans le répertoire &amp;quot;Téléchargements&amp;quot;&lt;br /&gt;
**télécharger [[Media:GpioSimulateur.zip]] dans le répertoire &amp;quot;Téléchargements&amp;quot;&lt;br /&gt;
**lancer un &amp;quot;émulateur de Terminal&amp;quot;, taper les commandes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
cd ~/Téléchargements/&lt;br /&gt;
rm gpioSimulateur&lt;br /&gt;
unzip GpioSimulateur.zip&lt;br /&gt;
chmod +x gpioSimulateur&lt;br /&gt;
./gpioSimulateur&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Vrac=&lt;br /&gt;
&lt;br /&gt;
==Idées==&lt;br /&gt;
&lt;br /&gt;
*classe filtrage capteur tor&lt;br /&gt;
*moyenne glissante capteur analogique&lt;br /&gt;
&lt;br /&gt;
==[[Cours:POONomenclature|Nomenclature diagramme objet]]==&lt;br /&gt;
&lt;br /&gt;
==Autres pages wiki utiles==&lt;br /&gt;
*[[Cours:modulesGrove]]&lt;br /&gt;
*[[Cours:rpi]]&lt;br /&gt;
*[[Cours:pooQT]]&lt;br /&gt;
*[[Cours:QT]]&lt;br /&gt;
*[[Cours:infoS3_POO_archives]]&lt;br /&gt;
&lt;br /&gt;
=Cas particuliers=&lt;br /&gt;
&lt;br /&gt;
==surcharge et signaux/slots==&lt;br /&gt;
&lt;br /&gt;
 Il faudra indiquer au compilateur le type des paramètres pour faire le choix du bon signal et/ou slot :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
    connect(ui-&amp;gt;doubleSpinBox,QOverload&amp;lt;double&amp;gt;::of(&amp;amp;QDoubleSpinBox::valueChanged),&lt;br /&gt;
            this,&amp;amp;MainWindow::afficheDouble);&lt;br /&gt;
    connect(ui-&amp;gt;doubleSpinBox,QOverload&amp;lt;double&amp;gt;::of(&amp;amp;QDoubleSpinBox::valueChanged),&lt;br /&gt;
            this,QOverload&amp;lt;double&amp;gt;::of(&amp;amp;MainWindow::affiche));&lt;br /&gt;
    connect(ui-&amp;gt;doubleSpinBox,QOverload&amp;lt;const QString &amp;amp;&amp;gt;::of(&amp;amp;QDoubleSpinBox::valueChanged),&lt;br /&gt;
            this,QOverload&amp;lt;const QString &amp;amp;&amp;gt;::of(&amp;amp;MainWindow::affiche));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:InfoS3_POO&amp;diff=21138</id>
		<title>Cours:InfoS3 POO</title>
		<link rel="alternate" type="text/html" href="https://wikigeii.iut-troyes.univ-reims.fr/index.php?title=Cours:InfoS3_POO&amp;diff=21138"/>
		<updated>2026-09-03T08:39:51Z</updated>

		<summary type="html">&lt;p&gt;Fredmn : /* Lecture externes potentiellement utiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Pratique =&lt;br /&gt;
&lt;br /&gt;
* Pour installer QT Creator (ainsi que C++ et Qt) sous de nombreux OS : suivre ce tutoriel &lt;br /&gt;
 https://guillaumebelz.github.io/qtinstall/&lt;br /&gt;
&lt;br /&gt;
* Guide d&#039;installation de Qt par Geoffrey Lecoq (merci à lui) : [[Fichier:GuideQT_Lecoq.pdf]]&lt;br /&gt;
&lt;br /&gt;
= Évaluations = &lt;br /&gt;
&lt;br /&gt;
*[[Cours:DevoirPOOcpp2|Évaluation n°1]]&lt;br /&gt;
*[[Cours:DevoirMaisonPOO1|Devoir maison n°1]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*[[Cours:DevoirPOO1|Évaluation n°1]]--&amp;gt;&lt;br /&gt;
*[[Cours:DevoirPOO2Ressources|Évaluation n°2 ressources]]&lt;br /&gt;
*[[Cours:DevoirPOO2|Évaluation n°2 sujet]]&lt;br /&gt;
&lt;br /&gt;
= Cours magistral =&lt;br /&gt;
&lt;br /&gt;
== Diapositives et support de cours ==&lt;br /&gt;
&lt;br /&gt;
* Diapositives de la partie Introduction : [[Media:POOintro.pdf]]&lt;br /&gt;
* Diapositives de la partie Notions : [[Media:POOnotions.pdf]]&lt;br /&gt;
* Diapositives de la partie Approfondissements : [[Media:POOapprofondissements.pdf]]&lt;br /&gt;
* Support de cours imprimable : [[Media:POOsupport.pdf]]&lt;br /&gt;
&lt;br /&gt;
== Projets de démonstration de CM ==&lt;br /&gt;
&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;minimal&amp;lt;/code&amp;gt; : [[Media:minimal.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;simpleNonOOCar&amp;lt;/code&amp;gt; : [[Media:simpleNonOOCar.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;simpleOOCar&amp;lt;/code&amp;gt; : [[Media:simpleOOCar.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;twoOOCars&amp;lt;/code&amp;gt; : [[Media:twoOOCars.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes_start&amp;lt;/code&amp;gt; : [[Media:formes_start.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes&amp;lt;/code&amp;gt; : [[Media:formes.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes_nonpolymorphes&amp;lt;/code&amp;gt; [[Media:formes_nonpolymorphes.zip]]&lt;br /&gt;
* Projet &amp;lt;code&amp;gt;formes_polymorphes&amp;lt;/code&amp;gt; [[Media:formes_polymorphes.zip]]&lt;br /&gt;
&lt;br /&gt;
== Lectures externes potentiellement utiles ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Cours de POO d&#039;openclassrooms&#039;&#039;&#039; :&lt;br /&gt;
&lt;br /&gt;
1. [https://openclassrooms.com/fr/courses/7137751-programmez-en-oriente-objet-avec-c/7673331-decouvrez-la-notion-de-poo Découvrez La notion de programmation orientée objet (POO)]&lt;br /&gt;
&lt;br /&gt;
2. [https://openclassrooms.com/fr/courses/7137751-programmez-en-oriente-objet-avec-c Programmez en orienté objet avec C++]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Les pointeurs et leur utilisation avec des objets&#039;&#039;&#039; :&lt;br /&gt;
&lt;br /&gt;
1. [https://openclassrooms.com/fr/courses/1894236-apprenez-a-programmer-en-c/7534366-declarez-les-pointeurs Déclarez les pointeurs]&lt;br /&gt;
&lt;br /&gt;
2. [https://openclassrooms.com/fr/courses/7137751-programmez-en-oriente-objet-avec-c/7531356-associez-les-classes-et-les-pointeurs Associez les classes et les pointeurs] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- [[media:POO-Support.pdf|Support de cours en pdf (à télécharger)]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Séances : C++ sous QT Creator =&lt;br /&gt;
&lt;br /&gt;
*[[Cours:pooTD1_ledsbps|séance 1 (4,5h) : découverte du C++ et de QT Creator]]&lt;br /&gt;
*[[Cours:pooTD2_barregraphe|séance 2 (1,5h) : Écriture d&#039;une classe (Barregraphe)]]&lt;br /&gt;
* séance 3 (1h) : Évaluation&lt;br /&gt;
*[[Cours:interfaceQT|séance 3 (1,5h) : 1ère interface graphique]]&lt;br /&gt;
*[[Cours:signalSlotQT|séance 4 (3h)  : classe avec slot et émission de signal]]&lt;br /&gt;
*[[Cours:TPheritageIO|séance 5 (3h): on hérite ! (pi4)]]&lt;br /&gt;
*[[Cours:pointeursCpp|séance 6 (1,5h) : manipulation de pointeurs/références]]&lt;br /&gt;
*[[Cours:DiyWidgetQT|séance 7 (3h) : création d&#039;un widget DIY]] (à déplacer pour utilisation dans le DM)&lt;br /&gt;
*[[Cours:TPqtFNS|séance 8 (1,5h) : Machine à état fini]]&lt;br /&gt;
*[[Cours:pooSignal|séance 9 (0,5h) : Emission de signal]]&lt;br /&gt;
*[[Cours:qtTCP|séance 10 (1,5h) : Révisions ou communication entre 2 cartes par TCP]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Archives==&lt;br /&gt;
*[[Cours:pooTD2_classes|séance 2 (3h) : création de classes et manipulation d&#039;objets]]&lt;br /&gt;
*{{Rouge|Evaluation (1,5h)}}&lt;br /&gt;
*[[Cours:interfaceQT|séance 3 (1,5h) : 1ère interface graphique]]&lt;br /&gt;
*[[Cours:signalSlotQT|séance 4 (1.5h)  : classe avec slot et émission de signal]]&lt;br /&gt;
*[[Cours:TPgpioQT|séance 5 (3h) : GPIO (pi4) ]]&lt;br /&gt;
*[[Cours:TPheritageIO|séance 6 (4,5h): on hérite ! (pi4)]]&lt;br /&gt;
*[[Cours:HeritageWidgetQT|séance 7 (1,5h) : spécialisation de Widgets]]&lt;br /&gt;
*[[Cours:TPqtFNS|séance 8 (3h) : Machine à état fini (&amp;quot;pi4&amp;quot;) ]]&lt;br /&gt;
*[[Cours:pointeursCpp|séance 9 (1,5h) : manipulation de pointeurs/références]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*{{Rouge|Evaluation (3h) (pi4)}}&lt;br /&gt;
&lt;br /&gt;
=Pour aller plus loin=&lt;br /&gt;
*[[Cours:diyWidgetQT|Créer son widget]]&lt;br /&gt;
*[[Cours:TPgpioControleur|Tp 2 : contrôleur de lampes]]&lt;br /&gt;
*[[Cours:gitQtCreator|Utilisation de git avec qt creator]]&lt;br /&gt;
&lt;br /&gt;
=Ressources=&lt;br /&gt;
*https://www.kdab.com/wp-content/uploads/stories/slides/DD13/dd13_signalsslots.pdf&lt;br /&gt;
&lt;br /&gt;
=Logiciel=&lt;br /&gt;
==Vm Qt Creator==&lt;br /&gt;
&lt;br /&gt;
Vous pouvez utiliser l&#039;image VirtualBox suivante sur laquelle QtCreator est installé&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1BdVNnAtpYM14ztf215gBVx5b2P8iAAix/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le mot de passe est geii&lt;br /&gt;
&lt;br /&gt;
==Simulation de gpio==&lt;br /&gt;
&lt;br /&gt;
*simulateur leds/bp/interrupteur&lt;br /&gt;
**dans la machine virtuelle VirtualBox&lt;br /&gt;
**au besoin supprimer le fichier GpioSimulateur.zip dans le répertoire &amp;quot;Téléchargements&amp;quot;&lt;br /&gt;
**télécharger [[Media:GpioSimulateur.zip]] dans le répertoire &amp;quot;Téléchargements&amp;quot;&lt;br /&gt;
**lancer un &amp;quot;émulateur de Terminal&amp;quot;, taper les commandes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
cd ~/Téléchargements/&lt;br /&gt;
rm gpioSimulateur&lt;br /&gt;
unzip GpioSimulateur.zip&lt;br /&gt;
chmod +x gpioSimulateur&lt;br /&gt;
./gpioSimulateur&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Vrac=&lt;br /&gt;
&lt;br /&gt;
==Idées==&lt;br /&gt;
&lt;br /&gt;
*classe filtrage capteur tor&lt;br /&gt;
*moyenne glissante capteur analogique&lt;br /&gt;
&lt;br /&gt;
==[[Cours:POONomenclature|Nomenclature diagramme objet]]==&lt;br /&gt;
&lt;br /&gt;
==Autres pages wiki utiles==&lt;br /&gt;
*[[Cours:modulesGrove]]&lt;br /&gt;
*[[Cours:rpi]]&lt;br /&gt;
*[[Cours:pooQT]]&lt;br /&gt;
*[[Cours:QT]]&lt;br /&gt;
*[[Cours:infoS3_POO_archives]]&lt;br /&gt;
&lt;br /&gt;
=Cas particuliers=&lt;br /&gt;
&lt;br /&gt;
==surcharge et signaux/slots==&lt;br /&gt;
&lt;br /&gt;
 Il faudra indiquer au compilateur le type des paramètres pour faire le choix du bon signal et/ou slot :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
    connect(ui-&amp;gt;doubleSpinBox,QOverload&amp;lt;double&amp;gt;::of(&amp;amp;QDoubleSpinBox::valueChanged),&lt;br /&gt;
            this,&amp;amp;MainWindow::afficheDouble);&lt;br /&gt;
    connect(ui-&amp;gt;doubleSpinBox,QOverload&amp;lt;double&amp;gt;::of(&amp;amp;QDoubleSpinBox::valueChanged),&lt;br /&gt;
            this,QOverload&amp;lt;double&amp;gt;::of(&amp;amp;MainWindow::affiche));&lt;br /&gt;
    connect(ui-&amp;gt;doubleSpinBox,QOverload&amp;lt;const QString &amp;amp;&amp;gt;::of(&amp;amp;QDoubleSpinBox::valueChanged),&lt;br /&gt;
            this,QOverload&amp;lt;const QString &amp;amp;&amp;gt;::of(&amp;amp;MainWindow::affiche));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s&#039;agit maintenant de transformer la variable &#039;&#039;s&#039;&#039; en une variable &#039;&#039;z&#039;&#039; :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; &#039;&#039;s = (2/Ts)*(z-1)/(z+1)&#039;&#039; (voir le cours)&lt;br /&gt;
* ou par &#039;&#039;backward euler&#039;&#039; (version un peu plus simple) : &amp;lt;br/&amp;gt;&#039;&#039;s = (z-1)/(Ts*z)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert &#039;&#039;H(s)&#039;&#039;, obtenir la fonction de transfert &#039;&#039;H(z)&#039;&#039; du filtre linéaire numérique correspondant (dans un premier temps avec &#039;&#039;backward Euler&#039;&#039;) :&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(&#039;K_i K_d K_p N T_s z s&#039;)&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&#039;obtenir &#039;&#039;H(z)&#039;&#039; sous la forme d&#039;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&#039;asservissement de drone et vérifier qu&#039;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&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s&#039;agit maintenant de transformer la variable &#039;&#039;s&#039;&#039; en une variable &#039;&#039;z&#039;&#039; :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; &#039;&#039;s = (2/Ts)*(z-1)/(z+1)&#039;&#039; (voir le cours)&lt;br /&gt;
* ou par &#039;&#039;backward euler&#039;&#039; (version un peu plus simple) : &amp;lt;br/&amp;gt;&#039;&#039;s = (z-1)/(Ts*z)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert &#039;&#039;H(s)&#039;&#039;, obtenir la fonction de transfert &#039;&#039;H(z)&#039;&#039; du filtre linéaire numérique correspondant (dans un premier temps avec &#039;&#039;backward Euler&#039;&#039;) :&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(&#039;K_i K_d K_p N T_s z s&#039;)&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&#039;obtenir &#039;&#039;H(z)&#039;&#039; sous la forme d&#039;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&#039;asservissement de drone et vérifier qu&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s&#039;agit maintenant de transformer la variable &#039;&#039;s&#039;&#039; en une variable &#039;&#039;z&#039;&#039; :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; &#039;&#039;s = (2/Ts)*(z-1)/(z+1)&#039;&#039; (voir le cours)&lt;br /&gt;
* ou par &#039;&#039;backward euler&#039;&#039; (version un peu plus simple) : &amp;lt;br/&amp;gt;&#039;&#039;s = (z-1)/(Ts*z)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert &#039;&#039;H(s)&#039;&#039;, obtenir la fonction de transfert &#039;&#039;H(z)&#039;&#039; du filtre linéaire numérique correspondant (dans un premier temps avec &#039;&#039;backward Euler&#039;&#039;) :&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(&#039;K_i K_d K_p N T_s z s&#039;)&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&#039;obtenir &#039;&#039;H(z)&#039;&#039; sous la forme d&#039;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&#039;asservissement de drone et vérifier qu&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s&#039;agit maintenant de transformer la variable &#039;&#039;s&#039;&#039; en une variable &#039;&#039;z&#039;&#039; :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; &#039;&#039;s = (2/Ts)*(z-1)/(z+1)&#039;&#039; (voir le cours)&lt;br /&gt;
* ou par &#039;&#039;backward euler&#039;&#039; (version un peu plus simple) : &amp;lt;br/&amp;gt;&#039;&#039;s = (z-1)/(Ts*z)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert &#039;&#039;H(s)&#039;&#039;, obtenir la fonction de transfert &#039;&#039;H(z)&#039;&#039; du filtre linéaire numérique correspondant (dans un premier temps avec &#039;&#039;backward Euler&#039;&#039;) :&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(&#039;K_i K_d K_p N T_s z s&#039;)&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&#039;obtenir &#039;&#039;H(z)&#039;&#039; sous la forme d&#039;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&#039;asservissement de drone et vérifier qu&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone : [[Media:TNS TP6 starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone.&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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&amp;#039;un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone.&lt;br /&gt;
&lt;br /&gt;
{{q | a}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
{{q | b}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
{{q | c}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
{{q | d}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; 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&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.&#039;&#039;d&#039;&#039;t&#039;&#039; où d&#039;&#039;t&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).&#039;&#039;d&#039;&#039;t&#039;&#039;&lt;br /&gt;
C&#039;est ainsi que vous avez implémenté vos PID jusqu&#039;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 &#039;&#039;z&#039;&#039; d&#039;un drone.&lt;br /&gt;
&lt;br /&gt;
{{q | a}} &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur statique.&lt;br /&gt;
{{q | b}} &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
{{q | c}} Le terme dérivatif n&#039;est pas nécessaire pour la température&lt;br /&gt;
{{q | d}} Mais l&#039;est pour asservir la position &#039;&#039;z&#039;&#039; du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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&#039;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&#039;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&#039;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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; 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 &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; 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 - &#039;&#039;Creating Your First Block&#039;&#039;]&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&#039;&#039; implique que &#039;&#039;y(n)&#039;&#039; doit être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&amp;quot; implique que &#039;&#039;y(n)&#039;&#039; doit pouvoir être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel - Bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;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 &#039;&#039;x(n)&#039;&#039; rentre dans le système&lt;br /&gt;
* le travail consiste à calculer &#039;&#039;y(n)&#039;&#039; avec l&#039;équation au différences du filtre, à partir de la valeur &#039;&#039;x(n)&#039;&#039; et de ses versions précédentes &#039;&#039;x(n-1)&#039;&#039; et &#039;&#039;x(n-2)&#039;&#039; (et aussi &#039;&#039;y(n-1)&#039;&#039;, &#039;&#039;y(n-2)&#039;&#039;) qu&#039;il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de &#039;&#039;temps réel&amp;quot; implique que &#039;&#039;y(n)&#039;&#039; doit pouvoir être calculer avant qu&#039;une nouvelle valeurs de &#039;&#039;x(n)&#039;&#039; ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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;
&#039;&#039;&#039;&amp;lt;big&amp;gt;S4 - ESE - Traitement numérique du signal&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;1,5h&lt;br /&gt;
* TD : 6 séances d&#039;1,5h + une évaluation d&#039;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&#039;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&#039;utilisateur (pas d&#039;utilisation d&#039;é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&#039;un fichier &amp;lt;/code&amp;gt;pixi.lock&amp;lt;/code&amp;gt; contenant description complète et déterministe de l&#039;environnement installé.&lt;br /&gt;
&lt;br /&gt;
Voici un guide :&lt;br /&gt;
# Installer pixi, en suivant l&#039;indication décrite dans https://pixi.prefix.dev/latest/installation/&amp;lt;br/&amp;gt;&#039;&#039;Note : l&#039;installation est locale à l&#039;utilisateur, elle ne sera nécessaire qu&#039;une seule fois pour le semestre&#039;&#039;&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; &#039;&#039;Incidemment, ces dépendances nécessitent python qui sera installé automatiquement (à l&#039;aide du dépot conda). Vous pouvez afficher le fichier pixi.toml pour observer ces dépendances.&#039;&#039;&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&#039;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;
&#039;&#039;&#039;Important&#039;&#039;&#039; :&lt;br /&gt;
* Il n&#039;est normalement pas nécessaire d&#039;éditer le fichier &amp;lt;code&amp;gt;pixi.toml&amp;lt;/code&amp;gt;&lt;br /&gt;
* Il n&#039;est &#039;&#039;&#039;jamais&#039;&#039;&#039; nécessaire d&#039;é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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel - Bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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&amp;#039;un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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&amp;#039;un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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&amp;#039;un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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 (&#039;&#039;w0/(w0+s)&#039;&#039;) 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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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&amp;#039;un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l&#039;é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 &#039;&#039;s&#039;&#039; ; intégrale =&amp;gt; division par &#039;&#039;s&#039;&#039;) :&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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;est pas nécessaire dans cet exemple car la température ne dépend que de la commande &#039;&#039;u(t)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** &#039;&#039;Ki = Kd = 0&#039;&#039; =&amp;gt; chercher le meilleur &#039;&#039;Kp&#039;&#039; =&amp;gt; erreur de régime permanent&lt;br /&gt;
** &#039;&#039;Kd = 0&#039;&#039; =&amp;gt; l&#039;introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n&#039;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&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.dt&#039;&#039; où &#039;&#039;dt&#039;&#039; est l&#039;intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/dt&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).dt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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 &#039;&#039;u(t)&#039;&#039; 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é : &#039;&#039;t = n.Ts&#039;&#039; où &#039;&#039;Ts&#039;&#039; est la période d&#039;échantillonnage.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l&#039;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 &#039;&#039;D = (e(n)-e(n-1))/Ts&#039;&#039;&lt;br /&gt;
** L&#039;intégrale est approximée en cumulant progressivement : &#039;&#039;I = I + e(n).Ts&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;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&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;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&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;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;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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>https://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="https://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>https://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="https://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>https://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="https://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>https://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="https://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>https://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="https://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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;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&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;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&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
	<entry>
		<id>https://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="https://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>https://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="https://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|&#039;&#039;&#039;Retour à la page du cours&#039;&#039;&#039;}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d&#039;un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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&#039;implémentation d&#039;un PID numérique sous forme d&#039;un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EN COURS DE RÉÉCRITURE (C++ vers Python)&#039;&#039;&#039;&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&#039;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 &#039;&#039;y(n)&#039;&#039; = &#039;&#039;x(n)&#039;&#039; ou encore &#039;&#039;H(z)&#039;&#039;=1. Il s&#039;agit donc d&#039;une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Suivez bien toutes les étapes, sans aller trop rapidement&#039;&#039;&#039;&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&#039;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&#039;on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n&#039;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&#039;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&#039;un module OOT, mais il n&#039;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&#039;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;
(&#039;sink&#039;, &#039;source&#039;, &#039;sync&#039;, &#039;decimator&#039;, &#039;interpolator&#039;, &#039;general&#039;, &#039;tagged_stream&#039;, &#039;hier&#039;, &#039;noblock&#039;)&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&#039;échantillons en sortie que le nombre d&#039;échantillons consommés depuis l&#039;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&#039;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 &#039;lib/passetout_impl.h&#039;...&lt;br /&gt;
Adding file &#039;lib/passetout_impl.cc&#039;...&lt;br /&gt;
Adding file &#039;include/gnuradio/monModule/passetout.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/docstrings/passetout_pydoc_template.h&#039;...&lt;br /&gt;
Adding file &#039;python/monModule/bindings/passetout_python.cc&#039;...&lt;br /&gt;
Adding file &#039;grc/monModule_passetout.block.yml&#039;...&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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;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&#039;on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d&#039;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&#039;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 (&#039;&#039;yet another markup language&#039;&#039;) 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: &#039;[monModule]&#039;&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 &#039;parameters&#039; 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 &#039;inputs&#039; list entry per input and one &#039;outputs&#039; 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;
#  &#039;file_format&#039; 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&#039;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&#039;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&#039;absence d&#039;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| &#039;&#039;&#039;Après ces étapes, et avant de lancer gnuRadio, appeler l&#039;enseignant qui va mettre à jours les bibliothèques partagées.&#039;&#039;&#039;}}. 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 &#039;&#039;reload&#039;&#039;)&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&#039;équation aux différence du filtre, &#039;&#039;ie&#039;&#039; écrire &#039;&#039;y(n)=&#039;&#039; en fonction de &#039;&#039;x(n)&#039;&#039;, &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;obtenir &#039;&#039;y(n)&#039;&#039; dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** &#039;&#039;x(n)&#039;&#039; est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d&#039;affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire &#039;&#039;y(n)&#039;&#039;.&lt;br /&gt;
** il sera nécessaire de stocker dans des &#039;&#039;&#039;attributs&#039;&#039;&#039; les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de &#039;&#039;x(n-1)&#039;&#039;, &#039;&#039;x(n-2)&#039;&#039;, &#039;&#039;y(n-1)&#039;&#039; et &#039;&#039;y(n-2)&#039;&#039;.&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&#039;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&#039;un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d&#039;un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** &#039;&#039;backward euler&#039;&#039;&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&#039;asservissement d&#039;altitude d&#039;un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>
	</entry>
</feed>