Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
main.cpp@4:1d58769720c6, 2020-06-05 (annotated)
- Committer:
- jdeschamps
- Date:
- Fri Jun 05 06:33:21 2020 +0000
- Revision:
- 4:1d58769720c6
- Parent:
- 3:b95fe07153f1
- Child:
- 5:3e44d8755e88
nouveau;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| dg81 | 0:5fb4c7e603cf | 1 | |
| dg81 | 0:5fb4c7e603cf | 2 | #include "mbed.h" |
| dg81 | 0:5fb4c7e603cf | 3 | /*************** Variables globales **************************/ |
| jdeschamps | 2:ee896365f8fe | 4 | volatile int flag_timer_etat=0; //ce timer séquence l'alimaentation des phases du moteur, sa fréquence est réglable avec le potentiomètre + trame vitesse |
| jdeschamps | 2:ee896365f8fe | 5 | volatile int flag_timer_reglage_vitesse=0; //ce timer lit le réglage de la vitesse tous les 0.1 s |
| jdeschamps | 2:ee896365f8fe | 6 | volatile int flag_fc_haut=0; //interruption sur SW2 |
| jdeschamps | 2:ee896365f8fe | 7 | volatile int flag_contact=0; //interruption sur SW3 |
| jdeschamps | 4:1d58769720c6 | 8 | volatile int flag_retour=0; |
| dg81 | 0:5fb4c7e603cf | 9 | /*************** Interfaces utilisés *************************/ |
| jdeschamps | 1:bb5b935c0aa9 | 10 | Serial pc(USBTX, USBRX,9600); // liaison USB |
| dg81 | 0:5fb4c7e603cf | 11 | Ticker timer_etat; // Interruptions temporelles (timout) |
| dg81 | 0:5fb4c7e603cf | 12 | Ticker timer_reglage_vitesse; |
| jdeschamps | 1:bb5b935c0aa9 | 13 | DigitalOut IN1(PTD3); // sorties logiques |
| jdeschamps | 1:bb5b935c0aa9 | 14 | DigitalOut IN2(PTC4); |
| jdeschamps | 1:bb5b935c0aa9 | 15 | DigitalOut IN3(PTD1); |
| jdeschamps | 1:bb5b935c0aa9 | 16 | DigitalOut IN4(PTC12); |
| jdeschamps | 1:bb5b935c0aa9 | 17 | DigitalOut ENA(PTA1); |
| jdeschamps | 1:bb5b935c0aa9 | 18 | DigitalOut ENB(PTD2); |
| jdeschamps | 1:bb5b935c0aa9 | 19 | AnalogIn ain0(A0); //(lecture potentiometre vitesse) // entrées analogiques |
| jdeschamps | 2:ee896365f8fe | 20 | AnalogIn ain1(A1); // (lecture potentiometre lecture position) |
| jdeschamps | 2:ee896365f8fe | 21 | InterruptIn fc_haut(SW2); // SW2 est associé à une interruption kbi s'appelant fc_haut |
| jdeschamps | 2:ee896365f8fe | 22 | InterruptIn contact(SW3); // SW3 est associé à une interruption kbi s'appelant contact |
| dg81 | 0:5fb4c7e603cf | 23 | /*************** Programmes d'interruption *******************/ |
| jdeschamps | 2:ee896365f8fe | 24 | void IT_timer_etat() { // sequencement phases moteur dont la fréquence est réglable potentiomètre/trame |
| dg81 | 0:5fb4c7e603cf | 25 | flag_timer_etat=1; |
| dg81 | 0:5fb4c7e603cf | 26 | } |
| jdeschamps | 2:ee896365f8fe | 27 | void IT_timer_reglage_vitesse() { // reglage de la vitesse tous les 100 ms |
| dg81 | 0:5fb4c7e603cf | 28 | flag_timer_reglage_vitesse=1; |
| dg81 | 0:5fb4c7e603cf | 29 | } |
| dg81 | 0:5fb4c7e603cf | 30 | void IT_fc_haut(){ // position haute atteinte (raz) |
| dg81 | 0:5fb4c7e603cf | 31 | flag_fc_haut=1; |
| dg81 | 0:5fb4c7e603cf | 32 | } |
| dg81 | 0:5fb4c7e603cf | 33 | void IT_contact(){ // contact avec echantillon (OK) |
| dg81 | 0:5fb4c7e603cf | 34 | flag_contact=1; |
| dg81 | 0:5fb4c7e603cf | 35 | } |
| jdeschamps | 4:1d58769720c6 | 36 | void IT_retour(){ |
| jdeschamps | 4:1d58769720c6 | 37 | flag_retour=1; |
| jdeschamps | 4:1d58769720c6 | 38 | } |
| dg81 | 0:5fb4c7e603cf | 39 | /*************** Programme Principal *************************/ |
| dg81 | 0:5fb4c7e603cf | 40 | int main() { |
| dg81 | 0:5fb4c7e603cf | 41 | // declaration des variables |
| dg81 | 0:5fb4c7e603cf | 42 | signed char etat=0; // etat varie de 0 à 7 pour représenter les 8 posiions du mpp |
| dg81 | 0:5fb4c7e603cf | 43 | signed char sens=0; // -1 : recule / 0 : stop / 1 : avance |
| dg81 | 0:5fb4c7e603cf | 44 | float Vpot,Vpos,periode,position_mesuree,frequence; // Vpot potentiomètre reglage vitesse |
| dg81 | 0:5fb4c7e603cf | 45 | // Vpos capteur de position monté sur vérin |
| dg81 | 0:5fb4c7e603cf | 46 | // position_mesurée : position estimée avec Vpos |
| dg81 | 0:5fb4c7e603cf | 47 | // periode : periode de l'IT etat (pilotage moteur) |
| dg81 | 0:5fb4c7e603cf | 48 | // frequence : frequence de l'IT etat (pilotage moteur) |
| jdeschamps | 2:ee896365f8fe | 49 | char command[30]; // buffer de réception du message |
| dg81 | 3:b95fe07153f1 | 50 | int Nb_pas =0; // comptage du nombre de 1/2 pas |
| dg81 | 3:b95fe07153f1 | 51 | int consigne_position =0; |
| dg81 | 3:b95fe07153f1 | 52 | // dans le cas du firgelli : |
| dg81 | 0:5fb4c7e603cf | 53 | float a=127.47; // coefficient etalonnage capteur de position |
| dg81 | 0:5fb4c7e603cf | 54 | float b=-6.23; // coefficient etalonnage capteur de position |
| dg81 | 0:5fb4c7e603cf | 55 | // Initialisations |
| dg81 | 0:5fb4c7e603cf | 56 | IN1=0; // moteur non alimenté |
| dg81 | 0:5fb4c7e603cf | 57 | IN2=0; |
| dg81 | 0:5fb4c7e603cf | 58 | IN3=0; |
| dg81 | 0:5fb4c7e603cf | 59 | IN4=0; |
| jdeschamps | 2:ee896365f8fe | 60 | timer_etat.attach(&IT_timer_etat, 0.01); // mise à jour de la commande moteur toutes les 10ms (100Hz) |
| dg81 | 0:5fb4c7e603cf | 61 | timer_reglage_vitesse.attach(&IT_timer_reglage_vitesse, 0.1); // mise à jour de la vitesse moteur par potentiomètre toutes les 0,1s |
| dg81 | 3:b95fe07153f1 | 62 | fc_haut.fall(&IT_fc_haut); // declaration des programmes kbi (SW2) |
| dg81 | 3:b95fe07153f1 | 63 | contact.fall(&IT_contact); // declaration des programmes kbi (SW3) |
| dg81 | 0:5fb4c7e603cf | 64 | // boucle programme principal |
| dg81 | 0:5fb4c7e603cf | 65 | while(1) { |
| dg81 | 0:5fb4c7e603cf | 66 | // on traite la liaison serie |
| dg81 | 0:5fb4c7e603cf | 67 | if (pc.readable()){ // test liaison serie |
| dg81 | 0:5fb4c7e603cf | 68 | pc.scanf("%s",command); // ecrit dans "command" la chaine reçue |
| dg81 | 0:5fb4c7e603cf | 69 | if(strcmp(command,"stop")==0) { |
| dg81 | 0:5fb4c7e603cf | 70 | sens=0; // si j'ai reçu "stop" désactivation du L298 et sens = 0 |
| dg81 | 0:5fb4c7e603cf | 71 | ENA=0; |
| dg81 | 0:5fb4c7e603cf | 72 | ENB=0; |
| dg81 | 0:5fb4c7e603cf | 73 | } |
| dg81 | 0:5fb4c7e603cf | 74 | else if (strcmp(command,"avant")==0){ |
| dg81 | 0:5fb4c7e603cf | 75 | sens=1; // si j'ai reçu "avant" activation du L298 et sens = 1 |
| dg81 | 0:5fb4c7e603cf | 76 | ENA=1; |
| dg81 | 0:5fb4c7e603cf | 77 | ENB=1; |
| dg81 | 0:5fb4c7e603cf | 78 | } |
| dg81 | 0:5fb4c7e603cf | 79 | else if (strcmp(command,"arriere")==0){ |
| dg81 | 0:5fb4c7e603cf | 80 | sens=-1; // si j'ai reçu "arriere" activation du L298 et sens = -1 |
| dg81 | 0:5fb4c7e603cf | 81 | ENA=1; |
| dg81 | 0:5fb4c7e603cf | 82 | ENB=1; |
| dg81 | 0:5fb4c7e603cf | 83 | } |
| dg81 | 0:5fb4c7e603cf | 84 | else if (strcmp(command,"fc_haut")==0){ |
| dg81 | 0:5fb4c7e603cf | 85 | sens=0; // si j'ai reçu "fc_haut" désactivation du L298 et position = 0 |
| dg81 | 0:5fb4c7e603cf | 86 | ENA=0; // (réinitialisation du nombre de pas) |
| dg81 | 0:5fb4c7e603cf | 87 | ENB=0; |
| dg81 | 3:b95fe07153f1 | 88 | Nb_pas=0; |
| dg81 | 0:5fb4c7e603cf | 89 | } |
| jdeschamps | 4:1d58769720c6 | 90 | else if (strcmp(command,"retour")==0){ |
| jdeschamps | 4:1d58769720c6 | 91 | sens=-1; |
| jdeschamps | 4:1d58769720c6 | 92 | ENA=1; |
| jdeschamps | 4:1d58769720c6 | 93 | ENB=1; |
| jdeschamps | 4:1d58769720c6 | 94 | Nb_pas--; |
| jdeschamps | 4:1d58769720c6 | 95 | Nb_pas=0; |
| jdeschamps | 4:1d58769720c6 | 96 | } |
| dg81 | 0:5fb4c7e603cf | 97 | else if (strcmp(command,"contact")==0){ |
| dg81 | 0:5fb4c7e603cf | 98 | sens=0; // si j'ai reçu "contact" désactivation du L298 et position = 0 |
| dg81 | 0:5fb4c7e603cf | 99 | ENA=0; |
| dg81 | 0:5fb4c7e603cf | 100 | ENB=0; |
| dg81 | 3:b95fe07153f1 | 101 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 102 | /******************** Traitement contact si firgelli *******************************************************/ |
| dg81 | 3:b95fe07153f1 | 103 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 104 | /*// en mode test sur système avec capteur de position |
| dg81 | 3:b95fe07153f1 | 105 | Vpos=ain1.read(); // lecture du capteur de position (firgelli) |
| dg81 | 3:b95fe07153f1 | 106 | position_mesuree=a*Vpos+b; // calcule la position (firgelli) |
| dg81 | 0:5fb4c7e603cf | 107 | printf("Npas : %d , Vpos : %f , Position mesuree : %f \n", position,Vpos,position_mesuree); |
| dg81 | 0:5fb4c7e603cf | 108 | // sur le vrai système |
| dg81 | 0:5fb4c7e603cf | 109 | //position_mesuree=position*0.0125; |
| dg81 | 3:b95fe07153f1 | 110 | //printf("nb pas = %d\n", position_mesuree); */ |
| dg81 | 3:b95fe07153f1 | 111 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 112 | /******************** Traitement contact si moteur pas à pas ************************************************/ |
| dg81 | 3:b95fe07153f1 | 113 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 114 | // en mode test sur système avec capteur de position |
| dg81 | 3:b95fe07153f1 | 115 | position_mesuree=Nb_pas*0.0125; |
| dg81 | 3:b95fe07153f1 | 116 | printf("Npas : %d , Vpos : %f , Position mesuree : %f \n", Nb_pas,Vpos,position_mesuree); |
| dg81 | 0:5fb4c7e603cf | 117 | } |
| dg81 | 0:5fb4c7e603cf | 118 | else if(strcmp(command,"vitesse")==0) { // trame vitesse : "vitesse<CR>XXXX<CR>" où XXXX représente la frequence de pilotage du moteur |
| dg81 | 0:5fb4c7e603cf | 119 | pc.scanf("%s",command); // lecture de XXXX la frequence de pilotage |
| dg81 | 0:5fb4c7e603cf | 120 | frequence=atoi(command); // change la chaine de caractères en entier |
| dg81 | 0:5fb4c7e603cf | 121 | periode=1/float(frequence); |
| dg81 | 0:5fb4c7e603cf | 122 | timer_etat.attach(&IT_timer_etat, periode); //on fixe la periode de pilotage du moteur |
| dg81 | 0:5fb4c7e603cf | 123 | } |
| dg81 | 0:5fb4c7e603cf | 124 | else if(strcmp(command,"position")==0) { |
| dg81 | 0:5fb4c7e603cf | 125 | pc.scanf("%s",command); |
| jdeschamps | 2:ee896365f8fe | 126 | consigne_position=atoi(command); |
| jdeschamps | 2:ee896365f8fe | 127 | |
| dg81 | 0:5fb4c7e603cf | 128 | } |
| jdeschamps | 4:1d58769720c6 | 129 | else if (Nb_pas<=0){ |
| jdeschamps | 4:1d58769720c6 | 130 | sens=0; |
| jdeschamps | 4:1d58769720c6 | 131 | ENA=0; |
| jdeschamps | 4:1d58769720c6 | 132 | ENB=0; |
| jdeschamps | 4:1d58769720c6 | 133 | } |
| jdeschamps | 4:1d58769720c6 | 134 | else if (position_mesuree<=0){ |
| jdeschamps | 4:1d58769720c6 | 135 | sens=0; |
| jdeschamps | 4:1d58769720c6 | 136 | ENA=0; |
| jdeschamps | 4:1d58769720c6 | 137 | ENB=0; |
| jdeschamps | 4:1d58769720c6 | 138 | } |
| dg81 | 0:5fb4c7e603cf | 139 | } |
| dg81 | 0:5fb4c7e603cf | 140 | // on traite la commande du moteur |
| dg81 | 0:5fb4c7e603cf | 141 | if (flag_timer_etat==1) |
| dg81 | 0:5fb4c7e603cf | 142 | { |
| dg81 | 0:5fb4c7e603cf | 143 | if (sens ==1) { |
| dg81 | 0:5fb4c7e603cf | 144 | etat++; |
| dg81 | 3:b95fe07153f1 | 145 | Nb_pas++; |
| dg81 | 0:5fb4c7e603cf | 146 | if (etat>7) etat=0; |
| dg81 | 0:5fb4c7e603cf | 147 | } |
| dg81 | 0:5fb4c7e603cf | 148 | else if (sens==-1){ |
| dg81 | 0:5fb4c7e603cf | 149 | etat--; |
| dg81 | 3:b95fe07153f1 | 150 | Nb_pas--; |
| dg81 | 0:5fb4c7e603cf | 151 | if (etat<0) etat=7; |
| dg81 | 0:5fb4c7e603cf | 152 | } |
| dg81 | 0:5fb4c7e603cf | 153 | switch (etat) { |
| dg81 | 0:5fb4c7e603cf | 154 | case 0 : |
| dg81 | 0:5fb4c7e603cf | 155 | IN1=1; |
| dg81 | 0:5fb4c7e603cf | 156 | IN2=0; |
| dg81 | 0:5fb4c7e603cf | 157 | IN3=0; |
| dg81 | 0:5fb4c7e603cf | 158 | IN4=0; |
| dg81 | 0:5fb4c7e603cf | 159 | break; |
| dg81 | 0:5fb4c7e603cf | 160 | case 1 : |
| dg81 | 0:5fb4c7e603cf | 161 | IN1=1; |
| dg81 | 0:5fb4c7e603cf | 162 | IN2=0; |
| dg81 | 0:5fb4c7e603cf | 163 | IN3=1; |
| dg81 | 0:5fb4c7e603cf | 164 | IN4=0; |
| dg81 | 0:5fb4c7e603cf | 165 | break; |
| dg81 | 0:5fb4c7e603cf | 166 | case 2 : |
| dg81 | 0:5fb4c7e603cf | 167 | IN1=0; |
| dg81 | 0:5fb4c7e603cf | 168 | IN2=0; |
| dg81 | 0:5fb4c7e603cf | 169 | IN3=1; |
| dg81 | 0:5fb4c7e603cf | 170 | IN4=0; |
| dg81 | 0:5fb4c7e603cf | 171 | break; |
| dg81 | 0:5fb4c7e603cf | 172 | case 3 : |
| dg81 | 0:5fb4c7e603cf | 173 | IN1=0; |
| dg81 | 0:5fb4c7e603cf | 174 | IN2=1; |
| dg81 | 0:5fb4c7e603cf | 175 | IN3=1; |
| dg81 | 0:5fb4c7e603cf | 176 | IN4=0; |
| dg81 | 0:5fb4c7e603cf | 177 | break; |
| dg81 | 0:5fb4c7e603cf | 178 | case 4 : |
| dg81 | 0:5fb4c7e603cf | 179 | IN1=0; |
| dg81 | 0:5fb4c7e603cf | 180 | IN2=1; |
| dg81 | 0:5fb4c7e603cf | 181 | IN3=0; |
| dg81 | 0:5fb4c7e603cf | 182 | IN4=0; |
| dg81 | 0:5fb4c7e603cf | 183 | break; |
| dg81 | 0:5fb4c7e603cf | 184 | case 5 : |
| dg81 | 0:5fb4c7e603cf | 185 | IN1=0; |
| dg81 | 0:5fb4c7e603cf | 186 | IN2=1; |
| dg81 | 0:5fb4c7e603cf | 187 | IN3=0; |
| dg81 | 0:5fb4c7e603cf | 188 | IN4=1; |
| dg81 | 0:5fb4c7e603cf | 189 | break; |
| dg81 | 0:5fb4c7e603cf | 190 | case 6 : |
| dg81 | 0:5fb4c7e603cf | 191 | IN1=0; |
| dg81 | 0:5fb4c7e603cf | 192 | IN2=0; |
| dg81 | 0:5fb4c7e603cf | 193 | IN3=0; |
| dg81 | 0:5fb4c7e603cf | 194 | IN4=1; |
| dg81 | 0:5fb4c7e603cf | 195 | break; |
| dg81 | 0:5fb4c7e603cf | 196 | case 7 : |
| dg81 | 0:5fb4c7e603cf | 197 | IN1=1; |
| dg81 | 0:5fb4c7e603cf | 198 | IN2=0; |
| dg81 | 0:5fb4c7e603cf | 199 | IN3=0; |
| dg81 | 0:5fb4c7e603cf | 200 | IN4=1; |
| dg81 | 0:5fb4c7e603cf | 201 | break; |
| dg81 | 0:5fb4c7e603cf | 202 | default : |
| dg81 | 0:5fb4c7e603cf | 203 | etat=0; |
| dg81 | 0:5fb4c7e603cf | 204 | } |
| dg81 | 0:5fb4c7e603cf | 205 | // printf ("etat = %d\n",etat); |
| dg81 | 0:5fb4c7e603cf | 206 | flag_timer_etat=0; |
| dg81 | 0:5fb4c7e603cf | 207 | } |
| dg81 | 0:5fb4c7e603cf | 208 | if (flag_fc_haut==1){ // si j'ai un appui sur BP fc_haut : désactivation du L298 et position = 0 |
| dg81 | 3:b95fe07153f1 | 209 | Nb_pas=0; |
| dg81 | 0:5fb4c7e603cf | 210 | sens=0; |
| dg81 | 0:5fb4c7e603cf | 211 | ENA=0; |
| dg81 | 0:5fb4c7e603cf | 212 | ENB=0; |
| dg81 | 0:5fb4c7e603cf | 213 | flag_fc_haut=0; |
| dg81 | 0:5fb4c7e603cf | 214 | } |
| jdeschamps | 4:1d58769720c6 | 215 | if (flag_retour==1){ |
| jdeschamps | 4:1d58769720c6 | 216 | sens=-1; |
| jdeschamps | 4:1d58769720c6 | 217 | ENA=1; |
| jdeschamps | 4:1d58769720c6 | 218 | ENB=1; |
| jdeschamps | 4:1d58769720c6 | 219 | flag_retour=0; |
| jdeschamps | 4:1d58769720c6 | 220 | } |
| dg81 | 0:5fb4c7e603cf | 221 | if (flag_contact==1){ // si j'ai un appui sur BP contact : désactivation du L298 et envoi de la position |
| dg81 | 3:b95fe07153f1 | 222 | sens=0; // si j'ai reçu "contact" désactivation du L298 et position = 0 |
| dg81 | 0:5fb4c7e603cf | 223 | ENA=0; |
| dg81 | 0:5fb4c7e603cf | 224 | ENB=0; |
| dg81 | 3:b95fe07153f1 | 225 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 226 | /******************** Traitement contact si firgelli *******************************************************/ |
| dg81 | 3:b95fe07153f1 | 227 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 228 | /*// en mode test sur système avec capteur de position |
| dg81 | 3:b95fe07153f1 | 229 | Vpos=ain1.read(); // lecture du capteur de position (firgelli) |
| dg81 | 3:b95fe07153f1 | 230 | position_mesuree=a*Vpos+b; // calcule la position (firgelli) |
| dg81 | 3:b95fe07153f1 | 231 | printf("Npas : %d , Vpos : %f , Position mesuree : %f \n", position,Vpos,position_mesuree); |
| dg81 | 3:b95fe07153f1 | 232 | // sur le vrai système |
| dg81 | 3:b95fe07153f1 | 233 | //position_mesuree=position*0.0125; |
| dg81 | 3:b95fe07153f1 | 234 | //printf("nb pas = %d\n", position_mesuree); */ |
| dg81 | 3:b95fe07153f1 | 235 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 236 | /******************** Traitement contact si moteur pas à pas ************************************************/ |
| dg81 | 3:b95fe07153f1 | 237 | /***********************************************************************************************************/ |
| dg81 | 3:b95fe07153f1 | 238 | // en mode test sur système avec capteur de position |
| dg81 | 3:b95fe07153f1 | 239 | position_mesuree=Nb_pas*0.0125; |
| jdeschamps | 4:1d58769720c6 | 240 | printf("Npas : %d , Vpos : %f , Position mesuree : %f mm \n", Nb_pas,Vpos,position_mesuree); |
| jdeschamps | 4:1d58769720c6 | 241 | flag_contact=0; |
| dg81 | 0:5fb4c7e603cf | 242 | } |
| dg81 | 0:5fb4c7e603cf | 243 | if (flag_timer_reglage_vitesse==1){ |
| dg81 | 0:5fb4c7e603cf | 244 | Vpot=ain0.read(); // Vpot varie de 0 à 100% (0 à 1) en fonction du réglage vitesse |
| dg81 | 0:5fb4c7e603cf | 245 | frequence= 700*(Vpot+1); // frequence varie de 700 Hz à 1400Hz) |
| dg81 | 0:5fb4c7e603cf | 246 | periode=1/float(frequence); |
| dg81 | 0:5fb4c7e603cf | 247 | timer_etat.attach(&IT_timer_etat, periode); // maj vitesse moteur par potentiomètre |
| dg81 | 0:5fb4c7e603cf | 248 | flag_timer_reglage_vitesse=0; |
| dg81 | 0:5fb4c7e603cf | 249 | } |
| dg81 | 0:5fb4c7e603cf | 250 | } |
| jdeschamps | 4:1d58769720c6 | 251 | } |