TP3 - Cas d'étude : Flexion de Poutre
BUTS PÉDAGOGIQUES
- Réappliquer les notions apprises précédemment (algorithmique, programmation)
- Revoir la lecture et l'écriture de fichiers texte
- Apprendre les lectures et écritures binaires dans des fichiers
- Apprendre à créer des widgets de manière dynamique (plutôt qu'avec Glade)
- Apprendre à utiliser la documentation d'une bibliothèque logicielle
Et enfin, les quatre étapes de ce cas d'étude vont vous préparer pour le projet Génie Informatique.
L'objectif du cas d'étude « Flexion de poutre circulaire encastrée » est d'aboutir à une petite application utilitaire pour la mécanique. Cette application permettra d'explorer les domaines d'élasticité selon quatre dimensions :
1. Le matériau de la poutre,
2. La longueur de la poutre,
3. Le diamètre de la poutre,
4. La force appliquée à l'extrémité de la poutre.
Tout déplierTout déplier - Tout replierTout replier
Cliquez sur les exercices pour dévoiler les instructions.
Exercice 1 • Cinq paramètres, trois informations (version 1)
Tout déplierTout déplier - Tout replierTout replier
REMARQUE : si vous souhaitez conserver intacte la version de l'exercice précédent, ne faîtes pas de copier-coller de votre projet ! Cela ne fonctionnera pas. Faîtes plutôt une sauvegarde ZIP ou 7z du répertoire du projet. Puis, continuez de travailler avec le même projet.
Nous avons vu dans les TP précédents comment manipuler les curseurs horizontaux, les boutons compteurs et les étiquettes. Vous allez maintenant pouvoir répliquer ces mécanismes pour réaliser l'application suivante :
Cette application calcule la flèche à l'extrémité (en mm) et la contrainte maximum à l'encastrement (en MPa), lors de la flexion d'une poutre circulaire encastrée, selon :
- Le module d'Young du matériau en GPa (noté E)
- La longueur de la poutre en mm (notée L)
- Le diamètre de la poutre en mm (noté D)
- La force appliquée à l'extrémité de la poutre en N (notée F)
Voici les formules que vous appliquerez pour calculer la flèche à l'extrémité de la poutre et la contrainte maximum à l'encastrement de la poutre :
La limite élastique en cisaillement du matériau (notée τe) se calcule en fonction de la limite élastique en traction (notée σe) comme suit :
• Pour les matériaux fragiles : τe = σe / 2
• Pour les matériaux ductiles : τe = σe / √3 ≈ σe / 1,732
Dans la suite nous allons choisir σe / 2 comme limite, car plus restrictive.
Si la contrainte maximum à l'encastrement de la poutre respecte la limite élastique du matériau (exprimée en MPa) divisée par 2 alors un message d'information en vert sera affiché, mais si elle dépasse ce sera un message d'avertissement en rouge qui sera affiché.
Vous êtes autorisés à réutiliser l'illustration suivante pour votre application : img.png
Selon les architectures machine, la bibliothèque mathématique standard math.h
définit la macro constante PI
ou M_PI
.
Avec Eclipse, avec le compilateur GCC, ce sera M_PI
en incluant math.h
:
#include <math.h>
Avec Visual Studio, ce sera M_PI
, mais en définissant d'abord la macro-constante _USE_MATH_DEFINES
:
#define _USE_MATH_DEFINES
#include <math.h>
Sinon, la définir soi-même par #define PI 4*atan(1)
Exercice 2 • Export des calculs, sauvegarde des paramètres (version 2)
Tout déplierTout déplier - Tout replierTout replier
REMARQUE : si vous souhaitez conserver intacte la version de l'exercice précédent, ne faîtes pas de copier-coller de votre projet ! Cela ne fonctionnera pas. Faîtes plutôt une sauvegarde ZIP ou 7z du répertoire du projet. Puis, continuez de travailler avec le même projet.
2.1 Génération d'un fichier CSV (version 2a)
Nous souhaitons proposer à l'utilisateur de facilement récupérer toutes les valeurs de sa simulation. Pour répondre à ce besoin nous allons ajouter une nouvelle fonctionnalité qui enregistre, dans un fichier CSV, le module d'Young et la limite élastique du matériau, la longueur et le diamètre de la poutre, la force appliquée à l'extrémité de la poutre, ainsi que la flèche et la contrainte maximum subie par la poutre (située à l'encastrement).
Les fichiers CSV (Comma-Separated Values) sont des fichiers ASCII (des fichiers de texte) où les valeurs sont séparées par des virgules (ou de préférences des point-virgules). Ces fichiers sont faciles à traiter et peuvent notamment être ouvert dans des tableurs.
Ajoutez un bouton dans votre interface de nom button_export_csv
et connectez le signal
avec la fonction clicked
on_button_export_csv_clicked()
.
La fonction on_button_export_csv_clicked()
va réaliser les opérations suivantes :
- Récupérer les valeurs courantes des boutons compteurs de l'interface
- Calculer la flèche et la contrainte
- Afficher dans un
printf()
le message "=== DEBUT ecriture du fichier CSV" - Ouvrir en écriture un fichier nommé
"valeurs.csv"
- Écrire les valeurs dans le fichier de sorte à obtenir un résultat similaire à ceci :
- Fermer le fichier
- Afficher dans un
printf()
le message "=== FIN ecriture du fichier CSV"
Avec le compilateur VC (sous Visual Studio), au lieu d'utiliser fopen()
et fprintf()
, vous utiliserez fopen_s()
et fprintf_s()
qui s'appellent de manière légèrement différente :FILE *desc ;
errno_t err ;
err = fopen_s(&desc, "valeurs.csv", "w") ;
if (err != 0) {
perror("Erreur ouverture fichier en ecriture");
}
else {
fprintf_s (desc, "la_chaine_a_ecrire");
fclose (desc);
}
Testez votre programme et vérifiez que le fichier valeurs.csv
a bien été créé. Vous allez ouvrir ce fichier :
- Tout d'abord avec
Notepad++
- Et ensuite avec
Excel
Maintenant nous allons faire en sorte que l'utilisateur puisse choisir le nom et l'emplacement du fichier qu'il veut créer. Pour ce faire, vous allez ajouter un File Chooser Button de nom filechooserbutton_csv
Le code de la fonction on_button_export_csv_clicked()
va devoir être modifié de façon à ne plus ouvrir systématiquement un fichier de nom "valeurs.csv" mais en récupérant le nom du fichier spécifié par l'utilisateur.
- Pour ce faire, vous utiliserez la fonction gtk_file_chooser_get_filename() afin de récupérer le nom du fichier (qui sera en fait le chemin absolu) qui sera décrit dans
filechooserbutton_csv
.- Voici le prototype de cette fonction :
const char *gtk_file_chooser_get_filename (GtkFileChooser *chooser) ;
- Remarque : cette fonction retourne une adresse mémoire qui a été allouée. Lorsque vous avez fini d'utiliser la chaîne de caractères, pensez à libérer la mémoire avec la fonction free().
- Voici le prototype de cette fonction :
- Changez aussi les deux
printf()
de manière à y faire apparaître le nom du fichier à ouvrir.
Lorsque vous testerez, après avoir cliqué sur le « file chooser button », vous pourrez choisir un nouvel emplacement et un nouveau nom de fichier en faisant comme suit :
2.2 Enregistrement des valeurs de l'application (version 2b)
Afin d'améliorer le confort de l'utilisateur, nous souhaitons qu'entre deux utilisations de l'application celle-ci redémarre avec les valeurs présentes lors de la dernière exécution. En d'autres termes, nous souhaitons qu'avant que l'application ne se termine, les valeurs courantes (module d'Young, limite élastique, longueur, diamètre, et force) soient enregistrées dans un fichier, et que lors du démarrage de l'application les valeurs initiales soit positionnées avec les valeurs de ce fichier.
Dans la fonction on_window1_destroy()
(et avant l'appel à gtk_main_quit();
bien entendu), sauvegarder dans un fichier binaire les valeurs du module d'Young et de limite élastique du matériau, de longueur et du diamètre de la poutre et de la force appliquée à l'extrémité de la poutre :
- Déclarer un descripteur de fichier.
- Ouvrir en mode écriture le fichier
"configuration"
avec la fonctionfopen()
- Écrire les cinq valeurs réelles avec la fonction
fwrite()
(voir exemple ecrire.c ci-après) - Fermer le fichier avec la fonction
fclose()
Avant de continuer, compiler et exécuter le programme afin que le fichier "configuration" soit créé.
Dans la fonction on_window1_realize()
, lire les cinq valeurs réelles dans le fichier binaire "configuration"
afin d'initialiser les valeurs du module d'Young et de limite élastique du matériau, de longueur et du diamètre de la poutre et de la force appliquée à l'extrémité de la poutre.
- Déclarer un descripteur de fichier.
- Déclarer cinq réels qui serviront à stocker les valeurs lues.
- Ouvrir en mode lecture le fichier
"configuration"
avec la fonctionfopen()
- Lire les cinq valeurs réelles avec la fonction
fread()
(voir exemple lire.c ci-après) - Fermer le fichier avec la fonction
fclose()
Maintenant, compiler et exécuter le programme afin que le fichier "configuration" soit lu et retrouver les valeurs précédentes dans l'interface.
Aparté sur les entrée/sorties binaires
Afin que vous réalisiez ensuite des entrées/sorties binaires, les manipulations suivantes ont pour but d'approfondir (ou confirmer) vos connaissances sur la représentation binaire des données dans les fichiers.
- Voici deux exemples d'écriture ecrire.c et de lecture lire.c qui utilisent la librairie standard. Téléchargez et testez ces deux exemples dans une console (avec
GCC
celà ira plus vite). Le premier programme génère deux fichiers. Le second programme lit les deux fichiers. Nous allons essayer de comprendre pourquoi ces deux fichiers sont radicalement différents. - Notez la taille en octets des deux fichiers qui ont été générés lors de l'exécution.
- Pour visualiser le codage binaire des fichiers, on utilise généralement un affichage hexadécimal du contenu. Le programme hexdump.c (que vous compilerez) va vous permettre de visualiser le contenu de fichiers en hexadécimal. Par exemple, la représentation hexadécimale
F1
correspond à l'octet11110001
ou encore2A
correspond à l'octet00101010
.- Observez le contenu du fichier 1 et relevez le code binaire pour chacun des trois entiers (sachant qu'un entier occupe 4 octets). Vérifiez qu'il s'agit bien de la représentation binaire de chacun des entiers.
- Observez le contenu du fichier 2 et cherchez le code hexadécimal de chaque octet dans la table ASCII ci-dessous (extraite de http://www.table-ascii.com) afin de retrouver le caractère associé.
- Observez le contenu du fichier 1 et relevez le code binaire pour chacun des trois entiers (sachant qu'un entier occupe 4 octets). Vérifiez qu'il s'agit bien de la représentation binaire de chacun des entiers.
- Maintenant que vous avez bien compris que les deux fichiers générés sont totalement différents, vérifiez que seul le fichier 2 peut être correctement ouvert avec
Notepad++
- Vous pouvez aussi observer en hexadécimal le contenu du fichier CSV du 1.1 et retrouver les premiers octets dans la table ASCII.
Il existe différents visualiseurs/éditeurs hexadécimaux :
• hexdump
ou hexedit
, mais ils ne sont pas installés sur vos machines.
• Différents plugins pour Eclipse
, mais ils ne sont pas installés sur vos machines.
• L'éditeur binaire de Visual Studio
(mais attention, qui ne gère pas l'ordre little-endian des octets) :
1. Aller dans Menu Fichier
> Ouvrir
> Fichier
2. Sélectionner le nom du fichier
3. Cliquer sur la flèche du bouton « Ouvrir » et choisir « Ouvrir avec… »
4. Sélectionner « Éditeur binaire » dans la liste et cliquer sur le bouton « OK »
Décimal Hex Binaire Caractère
------- --- -------- ------
000 00 00000000 NUL (Null char.)
001 01 00000001 SOH (Start of Header)
002 02 00000010 STX (Start of Text)
003 03 00000011 ETX (End of Text)
004 04 00000100 EOT (End of Transmission)
005 05 00000101 ENQ (Enquiry)
006 06 00000110 ACK (Acknowledgment)
007 07 00000111 BEL (Bell)
008 08 00001000 BS (Backspace)
009 09 00001001 HT (Horizontal Tab)
010 0A 00001010 LF (Line Feed)
011 0B 00001011 VT (Vertical Tab)
012 0C 00001100 FF (Form Feed)
013 0D 00001101 CR (Carriage Return)
014 0E 00001110 SO (Shift Out)
015 0F 00001111 SI (Shift In)
016 10 00010000 DLE (Data Link Escape)
017 11 00010001 DC1 (XON)(Device Control 1)
018 12 00010010 DC2 (Device Control 2)
019 13 00010011 DC3 (XOFF)(Device Control 3)
020 14 00010100 DC4 (Device Control 4)
021 15 00010101 NAK (Negative Acknowledgement)
022 16 00010110 SYN (Synchronous Idle)
023 17 00010111 ETB (End of Trans. Block)
024 18 00011000 CAN (Cancel)
025 19 00011001 EM (End of Medium)
026 1A 00011010 SUB (Substitute)
027 1B 00011011 ESC (Escape)
028 1C 00011100 FS (File Separator)
029 1D 00011101 GS (Group Separator)
030 1E 00011110 RS (Request to Send)(Record Separator)
031 1F 00011111 US (Unit Separator)
032 20 00100000 SP (Space)
033 21 00100001 ! (exclamation mark)
034 22 00100010 " (double quote)
035 23 00100011 # (number sign)
036 24 00100100 $ (dollar sign)
037 25 00100101 % (percent)
038 26 00100110 & (ampersand)
039 27 00100111 ' (single quote)
040 28 00101000 ( (left opening parenthesis)
041 29 00101001 ) (right closing parenthesis)
042 2A 00101010 * (asterisk)
043 2B 00101011 + (plus)
044 2C 00101100 , (comma)
045 2D 00101101 - (minus or dash)
046 2E 00101110 . (dot)
047 2F 00101111 / (forward slash)
048 30 00110000 0
049 31 00110001 1
050 32 00110010 2
051 33 00110011 3
052 34 00110100 4
053 35 00110101 5
054 36 00110110 6
055 37 00110111 7
056 38 00111000 8
057 39 00111001 9
058 3A 00111010 : (colon)
059 3B 00111011 ; (semi-colon)
060 3C 00111100 < (less than sign)
061 3D 00111101 = (equal sign)
062 3E 00111110 > (greater than sign)
063 3F 00111111 ? (question mark)
064 40 01000000 @ (AT symbol)
065 41 01000001 A
066 42 01000010 B
067 43 01000011 C
068 44 01000100 D
069 45 01000101 E
070 46 01000110 F
071 47 01000111 G
072 48 01001000 H
073 49 01001001 I
074 4A 01001010 J
075 4B 01001011 K
076 4C 01001100 L
077 4D 01001101 M
078 4E 01001110 N
079 4F 01001111 O
080 50 01010000 P
081 51 01010001 Q
082 52 01010010 R
083 53 01010011 S
084 54 01010100 T
085 55 01010101 U
086 56 01010110 V
087 57 01010111 W
088 58 01011000 X
089 59 01011001 Y
090 5A 01011010 Z
091 5B 01011011 [ (left opening bracket)
092 5C 01011100 \ (back slash)
093 5D 01011101 ] (right closing bracket)
094 5E 01011110 ^ (caret cirumflex)
095 5F 01011111 _ (underscore)
096 60 01100000 `
097 61 01100001 a
098 62 01100010 b
099 63 01100011 c
100 64 01100100 d
101 65 01100101 e
102 66 01100110 f
103 67 01100111 g
104 68 01101000 h
105 69 01101001 i
106 6A 01101010 j
107 6B 01101011 k
108 6C 01101100 l
109 6D 01101101 m
110 6E 01101110 n
111 6F 01101111 o
112 70 01110000 p
113 71 01110001 q
114 72 01110010 r
115 73 01110011 s
116 74 01110100 t
117 75 01110101 u
118 76 01110110 v
119 77 01110111 w
120 78 01111000 x
121 79 01111001 y
122 7A 01111010 z
123 7B 01111011 { (left opening brace)
124 7C 01111100 | (vertical bar)
125 7D 01111101 } (right closing brace)
126 7E 01111110 ~ (tilde)
127 7F 01111111 DEL (delete)
Exercice 3 • Option poutres creuses (version 3)
Tout déplierTout déplier - Tout replierTout replier
REMARQUE : si vous souhaitez conserver intacte la version de l'exercice précédent, ne faîtes pas de copier-coller de votre projet ! Cela ne fonctionnera pas. Faîtes plutôt une sauvegarde ZIP ou 7z du répertoire du projet. Puis, continuez de travailler avec le même projet.
En plus de faire le calcul de flexion pour des poutres pleines (ce qui était le cas jusqu'à présent), notre application va maintenant également permettre de faire le calcul de flexion pour des poutres creuses.
Les changements à effectuer sur l'interface sont les suivants :
- Deux boutons radios pour choisir entre les modes de calcul « Poutre pleine » et « Poutre creuse ». Pour que ces deux boutons soient associés au même groupe et fonctionnent de manière couplée, faîtes en sorte que le deuxième bouton soit du même groupe que le premier (voir la propriété « Groupe » de l'onglet « Général » dans Glade)
- Un curseur horizontal et un bouton compteur pour spécifier le diamètre interne de la poutre (pour le mode « Poutre creuse » uniquement)
Le signal
de chacun des deux radios boutons sera connecté à sa propre fonction. Deux actions seront à effectuer dans ces fonctions :toggled
- Griser ou dégriser, selon le besoin, les composants permettant de spécifier le diamètre interne de la poutre à l'aide de la fonction gtk_widget_set_sensitive()
- Faire un appel à la fonction
rafraichir_affichage()
Le code de la fonction rafraichir_affichage()
va devoir être modifié pour prendre en compte le deuxième mode de calcul possible. Le mode de calcul sera déterminé selon qu'un des boutons radios soit ou non activé, grâce à la fonction gtk_toggle_button_get_active(). Pour calculer la flèche à l'extrémité (en mm) et la contrainte maximum à l'encastrement (en MPa) de la poutre creuse, les valeurs et formules suivantes seront appliquées :
- Le module d'Young du matériau en GPa (noté E)
- La longueur de la poutre en mm (notée L)
- Le diamètre extérieur de la poutre en mm (noté D)
- Le diamètre intérieur de la poutre en mm (noté d)
- La force appliquée à l'extrémité de la poutre en N (notée F)
Attention, les fonctionnalités de génération de fichier CSV, et de redémarrage à l'identique de l'application, vont aussi être impactées par ce nouveau mode de calcul possible ! La valeur du diamètre interne doit être aussi inscrite dans le fichier binaire avant de quitter. De plus, l'utilisateur devra pouvoir retrouver actif le même mode de calcul au redémarrage de l'application. Enfin, si le mode poutre creuse est actif, alors la valeur du diamètre interne doit être aussi inscrite dans le fichier CSV.
Exercice 4 • Liste de matériaux (version 4)
Tout déplierTout déplier - Tout replierTout replier
REMARQUE : si vous souhaitez conserver intacte la version de l'exercice précédent, ne faîtes pas de copier-coller de votre projet ! Cela ne fonctionnera pas. Faîtes plutôt une sauvegarde ZIP ou 7z du répertoire du projet. Puis, continuez de travailler avec le même projet.
Nous souhaitons désormais, en plus de pouvoir spécifier manuellement la valeur du module d'Young et la limite élastique du matériau de la poutre, donner à l'utilisateur la possibilité de choisir ces deux valeurs dans une liste prédéfinie de matériaux.
Voici, à peu de choses près, ce que vous devriez obtenir à la fin :
Pour cela, un fichier ASCII contiendra la liste des matériaux, avec le nom du matériau, suivit sur les deux lignes suivantes des deux valeurs réelles le décrivant. Voici un exemple d'un tel fichier de configuration :
- Dans Glade vous créerez un
VBox
, de nomvbox_materiaux
et de taille 2, que vous laisserez vide (car c'est lors de l'exécution du programme, que des boutons radios seront créés et ajoutés dynamiquement dans la fenêtre).
- Dans la fonction
on_window1_realize()
, procéder à la lecture du fichier de configuration afin de créer les boutons radios pour chacun des matériaux.- La lecture du fichier se fera donc par trois lignes à chaque fois (pour chaque bouton radio) :
- Pour la première ligne des noms des matériaux, vous pourrez soit utiliser fgets(), soit lire caractère par caractère avec fgetc() jusqu'à atteindre la fin de ligne
- Puis, pour les deux lignes du module d'Young et de la limite élastique, vous pourrez lire avec deux fscanf()
- Le plus simple sera de déclarer un tableau
GtkRadioButton *G_rdb_mat[MAX];
en variable globale, suffisamment grand pour stocker quelques dizaines d'éléments. Une autre variable globaleG_nb_mat
permettra de connaître le nombre d'éléments réellement présents dans le tableau.- Pour créer les boutons radios, utiliser la fonction gtk_radio_button_new_with_label_from_widget()
- Vous donnerez alors le radio bouton « Définir » pour le paramètre
radio_group_member
- Vous donnerez alors le radio bouton « Définir » pour le paramètre
- Pour créer les boutons radios, utiliser la fonction gtk_radio_button_new_with_label_from_widget()
- Pour connecter le signal
"toggled"
de chaque bouton radio il faut utiliser la fonction g_signal_connect() en lui donnant quatre paramètres :GtkObject *object
: le widget qu'il faudra écouter, c.-à-d. le bouton radiochar *name
: le nom du signal, c.-à-d."toggled"
void (*func) (GtkObject *object, gpointer user_data)
: la fonction qui devra être appelée, c.-à-d. la fonction on_radiobutton_materiaux_toggled() que vous allez créer. Tous les boutons radios seront connectés sur cette même et unique fonction qui fera seulement un appel à rafraichir_affichage()gpointer func_data
: une donnée à transmettre, vous indiquerezNULL
- Enfin, chaque composant fraîchement créé sera ajouté dans
vbox_materiaux
à l'aide de la fonction gtk_box_pack_start(), puis rendu apparent avec la fonction gtk_widget_show()
- La lecture du fichier se fera donc par trois lignes à chaque fois (pour chaque bouton radio) :
- Modifier la fonction
rafraichir_affichage()
pour y procéder au parcours du tableauG_rdb_mat
pour tester si un des boutons radios est en cours de sélection avec la fonction gtk_toggle_button_get_active()
En ce qui concerne le message d'information, de respect ou dépassement de la limite élastique, vous allez le remplacer par un message plus informatif (et souvent utilisé dans le cahier des charges) : la valeur du coefficient de sécurité. Ce coefficient correspond à la division de τe par la contrainte maximum à l'encastrement.