Mesure de régime moteur

Bonjour,

Je suis pratiquant en loisir de voiture sur circuit, avec une veille Golf pour ceux que ça intéresse, et je voudrais réaliser un petit compte-tour de moteur pour enregistrer des données sur une carte SD.

Pour ce qui est de l'enregistrement sur carte SD, pas de problème, j'ai déjà fait il y a quelques temps...

En revanche, c'est pour aller mesurer le régime que j'ai un soucis. En effet, la méthode la plus simple mécaniquement et très certainement la plus économique est d'enrouler un "fil" autour du fil de la bougie, et de compter le temps écoulé entre deux étincelles. Connaissant le nombre de cylindres sur le moteur, on peut alors en déduire facilement le régime moteur. Voici une illustration sur une moto : http://comptetours.free.fr/mostro/imgs/mecanique/PhotoSpires.jpg

Mon problème est le suivant : n'étant pas du tout électronicien, et pratiquant vraiment l'Arduino en loisir, je n'ai aucune idée du fonctionnement d'un tel système. J'ai bien trouvé ça (http://powerdyn.fr/French/img/schem.gif) sur le net, ce qui est un bon début, mais je ne comprend pas vraiment le montage, et je ne sais également pas où acheter le fil pour enrouler autour du fil de la bougie.

Bref, si vous pourriez me valider (ou non) le schéma ainsi que m'indiquer si vous déjà réalisé de tels montages, je suis vraiment intéressé, car là je patauge.

Merci par avance pour votre aide

Oublie cette méthode qui peut au mieux te griller ton Arduino et au pire te faire prendre quelques secousses électriques HT.

Sur pratiquement tous les alternateurs se trouve une cosse nommée "w" elle sert de prise de compte tour pour les véhicules diesel.

Tu mets un optocoupleur sur cette prise et ensuite tu viens sur un pin digitale de ton Arduino... tu comptes le temps entre les impulsions et tu as ton compte-tour.

Autre question, pensez-vous que ma carte Arduino MEGA soit capable de mesurer le temps entre deux intervalles, qui seront au maximum à une fréquence de 300Hz environ, soit environ tout les 0,0033 secondes, ce qui me paraît infime!

Je cherche le code que j'avais fait pour mon diesel et je te le poste.... tu peux facilement monter à 30'000t/min... ta golf supportera ? XD

Jean-François:
Oublie cette méthode qui peut au mieux te griller ton Arduino et au pire te faire prendre quelques secousses électriques HT.

Sur pratiquement tous les alternateurs se trouve une cosse nommée "w" elle sert de prise de compte tour pour les véhicules diesel.

Tu mets un optocoupleur sur cette prise et ensuite tu viens sur un pin digitale de ton Arduino... tu comptes le temps entre les impulsions et tu as ton compte-tour.

Merci beaucoup pour cette réponse ultra rapide JF.

Merci je ne connaissais pas les optocoupleurs, je viens de regarder sur wikipédia. Malheureusement, j'aimerai également à l'avenir utiliser ce système sur des moteurs 2T, qui pour le coup n'ont pas d'alternateur, et hormis mesurer le régime de cette façon je ne vois pas vraiment comment faire...

N'est-il pas possible de mettre un octocoupleur entre le fil de bougie et une masse et donc lire les informations? Grâce à ce composant mon circuit serait protégé non?

Jean-François:
Je cherche le code que j'avais fait pour mon diesel et je te le poste.... tu peux facilement monter à 30'000t/min... ta golf supportera ? XD

30000 tr, oui ça devrait aller :slight_smile: :slight_smile: :slight_smile: :slight_smile:

Déjà le code :

 volatile byte rpmcount;

 unsigned int rpm;

 unsigned long timeold;

 void setup()
 {
   Serial.begin(9600);
   attachInterrupt(0, rpm_fun, FALLING);

   rpmcount = 0;
   rpm = 0;
   timeold = 0;
 }

 void loop()
 {
   if (rpmcount >= 250) { 
     //Update RPM every 20 counts, increase this for better RPM resolution,
     //decrease for faster update
     rpm = 30*1000/(millis() - timeold)*rpmcount/75;
     timeold = millis();
     rpmcount = 0;
     Serial.println(rpm,DEC);
   }
 }

 void rpm_fun()
 {
   rpmcount++;
   //Each rotation, this interrupt function is run twice
 }

Il utilise une interruption, regarde ici comment ça fonctionne...

Pour le 2T il existe d'autres solutions, mais surtout pas celle que tu proposes.
Ta moto, allumage conventionnel (rupteurs) ou électronique ?

Jean-François:
Déjà le code :

 volatile byte rpmcount;

unsigned int rpm;

unsigned long timeold;

void setup()
{
   Serial.begin(9600);
   attachInterrupt(0, rpm_fun, FALLING);

rpmcount = 0;
   rpm = 0;
   timeold = 0;
}

void loop()
{
   if (rpmcount >= 250) {
     //Update RPM every 20 counts, increase this for better RPM resolution,
     //decrease for faster update
     rpm = 30*1000/(millis() - timeold)*rpmcount/75;
     timeold = millis();
     rpmcount = 0;
     Serial.println(rpm,DEC);
   }
}

void rpm_fun()
{
   rpmcount++;
   //Each rotation, this interrupt function is run twice
}




Il utilise une interruption, regarde [http://arduino.cc/en/Reference/AttachInterrupt](http://ici) comment ça fonctionne... 

Pour le 2T il existe d'autres solutions, mais surtout pas celle que tu proposes.
Ta moto, allumage conventionnel (rupteurs) ou électronique ?

Merci beaucoup pour ce code, c'est très sympa de ta part.

Ce n'est pas une moto mais un kart, et pour l'allumage c'est un allumage électronique, j'ai un boîtier qui régule pour ne pas dépasser un certain régime. Sinon c'est une bobine qui envoi l'impulsion à la bougie. Voilà, as-tu une idée pour mesurer le régime?

Sinon j'ai bien d'autres idées pour aller mesurer mon régime, comme mettre une cible avec des dents en queue de vilebrequin ou sur l'arbre de transmission, et compter l'intervalle de temps entre le passage de chaque dent, mais le problème c'est que mécaniquement ce n'est pas super propre, et ça n'est pas très discret non plus...

Le top pour moi serait de faire comme les système de chronométrage Alfano ou Mychron, qui enroulent un fil autour de celui de la bougie, mais après si tu me dis que c'est trop compliqué.... L'avantage de ce système c'est qu'il est hyper simple à mettre en œuvre sur le kart, pas besoin de mettre des cibles et des capteurs dans tout les sens, surtout que si je fais des courses je serai obligé de le démonter car en kart tu n'as pas le droit à plus de deux sondes d'acquis je crois. Voilà pourquoi j'ai tout de suite proposé ça.

En tout cas merci beaucoup pour ton aide,

Un repiquage sur le capteur du point d'allumage... ça fait déjà une sonde que tu n'utilise pas XD.

regarde ici :

http://arduino.cc/forum/index.php/topic,88051.0.html

Il me semble que la finalité de ce post est ce que tu recherches.

Jean-François:
Un repiquage sur le capteur du point d'allumage... ça fait déjà une sonde que tu n'utilise pas XD.

regarde ici :

http://arduino.cc/forum/index.php/topic,88051.0.html

Il me semble que la finalité de ce post est ce que tu recherches.

Jean-François, désolé pour ma réponse tardive mais j'ai un emploi du temps quelque peu chargé en ce moment...

Oui en effet, la finalité de ce post est exactement ce que je veux faire. A l'exception près que (et je ne l'avais pas précisé) je ne veux surtout pas modifier le faisceau d'allumage sinon je ne pourrais plus rouler avec en course. Voilà pourquoi la mesure par induction me plaît tant... (Désolé tu dois me trouver lourdingue.... :()

Dans tout les cas, merci beaucoup pour tes nombreuses réponses, je vais tâcher de mettre à profit les quelques pistes que tu m'as donné.

Et si toi ou quelqu'un a une autre idée, je suis toujours preneur!

Merci.

Salut,

Il est tout à fait possible d'utiliser un enroulement autour d'un fil de bougie, je l'ai déjà fait. Je déclenchais un NE555 avec 20 tours de fils telecomm autourdu fil qui sort de la bobine. Pour protéger l'arduino, il suffit de faire le schéma suivant :

L1 : une vingtaine (max) d'enroulements autour du fil qui sort de la bobine vers le distributeur (delco),
R2, D1 : protection de Q1
Q1, R1 : adaptation du signal en TTL
J1 à J3 : à brancher sur l'arduino.

Pour le code, c'est plus compliqué... il faut gérer une interruption et un timer...

const word rmp_facteur 30  //  pour moteur 4 cylindres 4 temps : =60/(nombre d'étincelles par tour moteur)
volatile word rmp_count = 0;  // variable de comptage vitesse du moteur
volatile word rmp_temp; // variable de lecture du timer
volatile word rmp_moteur;  // contient la vitesse moteur en tr/min


ISR (INT0_vect){                  // appelée à chaque étincelle de bougie
  rpm_count++;  // incrément compteur
}

ISR (TIMER1_COMPA_vect) { appelée à chaque tour de timer, soit toutes les 1s.
  rpm_temp = rmp_count;  // lecture compteur.
  rmp_count = 0;  // RAZ compteur
  rmp_moteur = rmp_temp * rmp_facteur;  // convertion en tour / minutes
}

void setup(){
  OCR1A = 62500;  // mesure moteur toutes les secondes
  TCCR1A = 0x00;  // configuration timer : mode normal CTC (RAZ sur comparaison OCR1A)
  TCCR1B = 0x0C;  // fréquence timer = 62.5KHz
  TMISK1 = 0x02;   // Interruption sur TCNT1 = OCR1A
  EICRA = 0x02;  // interruption INT0 déclenchée sur front descendant (falling);
  EIMSK = 0x01;  // autoriser l'INT0
}

void loop(){
  // ici, on utilise la valeur contenue dans rmp_moteur comme on veut (sans la modifier, cela va de soi). elle sera 
  //  mise à jour une fois par seconde...
}

Voilà.

Normalement, ça marche, c'est ce que j'ai fait pour mon régulateur de vitesse. Mais une actualisation une fois par seconde, c'est très moyen et la résolution de la mesure sera de rmp_facteur (30 pour un moteur 4c/4t) Il vaudrait mieux utiliser le signal de ton capteur PMH : il serait bien plus précis (40 impulsions par tour moteur sur mes moteurs Cléon, j'arrive à une mesure actualisée 4 fois par seconde avec une résolution de 5 tr/min environ, c'est bien plus fluide!)

Mais attention, toute fonction utilisant le timer1 est à oublier... sinon, tu vas te retrouver avec n'importequoi...

variante pour une actualisation 4 fois par seconde, mais beaucoup moins précise à bas régime :

remplacer la première ligne et le setup par :

const float rmp_facteur 3.75  //  pour moteur 4 cylindres 4 temps : =15/(nombre d'étincelles par tour moteur)

void setup(){
  OCR1A = 62500;  // mesure moteur toutes les 250ms
  TCCR1A = 0x00;  // configuration timer : mode normal CTC (RAZ sur comparaison OCR1A)
  TCCR1B = 0x0B;  // fréquence timer = 250KHz
  TMISK1 = 0x02;   // Interruption sur fin compteur
  EICRA = 0x02;  // interruption INT0 déclenchée sur front descendant (falling);
  EIMSK = 0x01;  // autoriser l'INT0
}

bien sûr, il serait préférable de trouver une valeur de OCR1A qui done un rmp_facteur entier, car les calculs float sont longs et peu précis dans notre cas...

T'es sûr que t'as pas le droit de juste repiquer le signal de ton capteur PMH?

Super_Cinci:
Salut,

Il est tout à fait possible d'utiliser un enroulement autour d'un fil de bougie, je l'ai déjà fait. Je déclenchais un NE555 avec 20 tours de fils telecomm autourdu fil qui sort de la bobine. Pour protéger l'arduino, il suffit de faire le schéma suivant :

L1 : une vingtaine (max) d'enroulements autour du fil qui sort de la bobine vers le distributeur (delco),
R2, D1 : protection de Q1
Q1, R1 : adaptation du signal en TTL
J1 à J3 : à brancher sur l'arduino.

Pour le code, c'est plus compliqué... il faut gérer une interruption et un timer...

const word rmp_facteur 30  //  pour moteur 4 cylindres 4 temps : =60/(nombre d'étincelles par tour moteur)

volatile word rmp_count = 0; // variable de comptage vitesse du moteur
volatile word rmp_temp; // variable de lecture du timer
volatile word rmp_moteur; // contient la vitesse moteur en tr/min

ISR (INT0_vect){ // appelée à chaque étincelle de bougie
rpm_count++; // incrément compteur
}

ISR (TIMER1_COMPA_vect) { appelée à chaque tour de timer, soit toutes les 1s.
rpm_temp = rmp_count; // lecture compteur.
rmp_count = 0; // RAZ compteur
rmp_moteur = rmp_temp * rmp_facteur; // convertion en tour / minutes
}

void setup(){
OCR1A = 62500; // mesure moteur toutes les secondes
TCCR1A = 0x00; // configuration timer : mode normal CTC (RAZ sur comparaison OCR1A)
TCCR1B = 0x0C; // fréquence timer = 62.5KHz
TMISK1 = 0x02; // Interruption sur TCNT1 = OCR1A
EICRA = 0x02; // interruption INT0 déclenchée sur front descendant (falling);
EIMSK = 0x01; // autoriser l'INT0
}

void loop(){
// ici, on utilise la valeur contenue dans rmp_moteur comme on veut (sans la modifier, cela va de soi). elle sera
// mise à jour une fois par seconde...
}



Voilà. 

Normalement, ça marche, c'est ce que j'ai fait pour mon régulateur de vitesse. Mais une actualisation une fois par seconde, c'est très moyen et la résolution de la mesure sera de rmp_facteur (30 pour un moteur 4c/4t) Il vaudrait mieux utiliser le signal de ton capteur PMH : il serait bien plus précis (40 impulsions par tour moteur sur mes moteurs Cléon, j'arrive à une mesure actualisée 4 fois par seconde avec une résolution de 5 tr/min environ, c'est bien plus fluide!)

Mais attention, toute fonction utilisant le timer1 est à oublier... sinon, tu vas te retrouver avec n'importequoi...

variante pour une actualisation 4 fois par seconde, mais beaucoup moins précise à bas régime :

remplacer la première ligne et le setup par :


const float rmp_facteur 3.75 // pour moteur 4 cylindres 4 temps : =15/(nombre d'étincelles par tour moteur)

void setup(){
OCR1A = 62500; // mesure moteur toutes les 250ms
TCCR1A = 0x00; // configuration timer : mode normal CTC (RAZ sur comparaison OCR1A)
TCCR1B = 0x0B; // fréquence timer = 250KHz
TMISK1 = 0x02; // Interruption sur fin compteur
EICRA = 0x02; // interruption INT0 déclenchée sur front descendant (falling);
EIMSK = 0x01; // autoriser l'INT0
}



bien sûr, il serait préférable de trouver une valeur de OCR1A qui done un rmp_facteur entier, car les calculs float sont longs et peu précis dans notre cas...

T'es sûr que t'as pas le droit de juste repiquer le signal de ton capteur PMH?

Super, merci beaucoup pour cette aide ma fois bien précieuse. Pour ce qui est de la précision, je n'ai pas besoin non plus d'être au tour près, c'est déjà pas mal si j'arrive à avoir un ordre d'idée du régime.

Pour ce qui est du repiquage au point d'allumage, je ne serais pas contre mais le problème c'est que toute modification du faisceau et totalement interdite. De plus, je n'ai pas le moteur sous les yeux, mais pour moi sur mon moteur de kart je n'ai qu'une impulsion par tour, et c'est un deux temps, donc ça ne changera pas grand chose....

En tout cas merci beaucoup, je commence à regarder ça ce week-end tranquillement car la semaine je n'ai pas vraiment le temps!

Merci beaucoup pour votre aide en tout cas, et vive ce forum qui m'aide bien souvent!!!!

Merci pour ces précisions Supe_Cinci.

Est ce que ce ne serait pas possible d'utiliser la fonction pulsIn() ?

Jean-François:
Merci pour ces précisions Supe_Cinci.

Est ce que ce ne serait pas possible d'utiliser la fonction pulsIn() ?

Tu commences à me connaître, je supporte de moins en moins les fonctions arduino... XD je ne sais même pas comment elle fonctionne, cette fonction... Je crois qu'elle utilise bêtement la fonction millis(), mais qui dit que l'arduino peut continuer à faire autre chose pendant la mesure de pulsIn()? dans mon code, loop() est vide, donc à part une ou deux int de temps en temps, le code peut s'exécuter en continu. sur mon régulateur de vitesse, c'est codé de la même façon, loop() ne sert qu'à gérer le clavier et donc les menus. même le LCD s'actualise via les timers. Si l'on doit lancer une mesure et attendre résultat, c'est pas très glop... :.

Cette fonction ne doit pas fonctionner avec millis, car elle compte les microsecondes entre deux impulsions.... par contre pour le reste je ne sais pas.

A 30'000 t/min, ça fait 2000 microsecondes par tour (sauf erreur de ma part :grin: ), je n'ai aucune idée si ce serait plus précis que ta fonction, mais ce serait intéressant à vérifier.

unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout){

// cache the port and bit of the pin in order to speed up the
	// pulse width measuring loop and achieve finer resolution.  calling
	// digitalRead() instead yields much coarser resolution.
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	uint8_t stateMask = (state ? bit : 0);
	unsigned long width = 0; // keep initialization out of time critical area
	
// convert the timeout from microseconds to a number of times through
	// the initial loop; it takes 16 clock cycles per iteration.
	unsigned long numloops = 0;
	unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
	
// wait for any previous pulse to end
	while ((*portInputRegister(port) & bit) == stateMask) if (numloops++ == maxloops) return 0;
	
// wait for the pulse to start
	while ((*portInputRegister(port) & bit) != stateMask) if (numloops++ == maxloops) return 0;
	
// wait for the pulse to stop
	while ((*portInputRegister(port) & bit) == stateMask) {
		if (numloops++ == maxloops) return 0;
		width++;
	}
	return clockCyclesToMicroseconds(width * 21 + 16); 
}

Bon, ben tout est là : il n'y a que des while... donc c'est une fonction qui fait perdre énormément de temps... Par contre, elle n'utilise aucun timer ni interruption, et ça marche sur toutes les pins... à voir selon ce que l'on veut faire en plus...

Petit EDIT du matin, la nuit porte conseil...

Si jamais on utilise une interruption et qu'elle intervient pendant pulseIn(), la mesure sera faussée (pulseIn() part sur le nombre de cycles que prennent les boucles while, ce qui fait que toute interruption du code n'est pas comptée, ralenti les boucles, donc diminue la valeur retournée).

rien que :

#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))

// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)

// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)

volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;

SIGNAL(TIMER0_OVF_vect)
{
	// copy these to local variables so they can be stored in registers
	// (volatile variables must be read from memory on every access)
	unsigned long m = timer0_millis;
	unsigned char f = timer0_fract;

	m += MILLIS_INC;
	f += FRACT_INC;
	if (f >= FRACT_MAX) {
		f -= FRACT_MAX;
		m += 1;
	}

	timer0_fract = f;
	timer0_millis = m;
	timer0_overflow_count++;
}

c'est l'interruption overflow du timer0 qui met à jour les données utilisées dans millis() et micros(), je ne suis pas sûr que ce soit prévu dans le code de pulseIn(), alors oui, c'est ma proc la plus précise...

Et en utilisant micros() en comptant la différence entre chaque étincelle, avec un lissage sur trois-quatre mesure, ça n'irait pas ?

Je n'avais pas pris le temps de regarder le code avant ce soir. C'est exactement ce qu'il me faut, je te remercie beaucoup.

J'ai trois questions. J'ai essayé de comprendre ton code, et comme je débute je peine à tout comprendre. Cependant, si j'ai bien compris, tu surveilles les impulsions entrantes dans l'Arduino dans le setup en même temps que tu exécute ton programme dans le loop. Je ne savais pas que c'était possible avec Arduino, c'est donc possible de faire du multitâche?

Seconde question :

Super_Cinci:
Il est tout à fait possible d'utiliser un enroulement autour d'un fil de bougie, je l'ai déjà fait. Je déclenchais un NE555 avec 20 tours de fils telecomm autourdu fil qui sort de la bobine. Pour protéger l'arduino, il suffit de faire le schéma suivant :

Sur ton schéma je ne comprend pas ou tu branches ton NE555 en fait :blush: :blush: :blush: Il est où sur ton schéma? Au niveau de ton J2 tu te branches sur l'Arduino ou sur ton NE555?

Dernière question un peu plus terre à terre, qu'appelle-tu du fil telecom?

Merci je vais essayer de mettre ça en application.

catsur:
Je n'avais pas pris le temps de regarder le code avant ce soir. C'est exactement ce qu'il me faut, je te remercie beaucoup.

ça t'aidera sûrement, mais en effet :

catsur:
J'ai trois questions

pour l'instant... :wink:

catsur:
. J'ai essayé de comprendre ton code, et comme je débute je peine à tout comprendre. Cependant, si j'ai bien compris, tu surveilles les impulsions entrantes dans l'Arduino dans le setup en même temps que tu exécute ton programme dans le loop. Je ne savais pas que c'était possible avec Arduino, c'est donc possible de faire du multitâche?

Non, ce n'est pas du multitâche au sens de ce qu'il se passe dans ton PC. Une interruption est un évènement physique qui peut intervenir à tout moment : une impulsion sur une entrée spécifique, un timer qui arrive à une certaine valeur... Dès que cet évènement se produit, alors l'arduino stoppe tout ce qu'il faisait avant, et fait ce que tu lui as demandé de faire dans une telle situation (ISR). une fois qu'il a fait ce que tu lui avais dit de faire, il reprend là où il en était avant.

catsur:
Seconde question :

Super_Cinci:
Il est tout à fait possible d'utiliser un enroulement autour d'un fil de bougie, je l'ai déjà fait. Je déclenchais un NE555 avec 20 tours de fils telecomm autourdu fil qui sort de la bobine. Pour protéger l'arduino, il suffit de faire le schéma suivant :

Sur ton schéma je ne comprend pas ou tu branches ton NE555 en fait :blush: :blush: :blush: Il est où sur ton schéma? Au niveau de ton J2 tu te branches sur l'Arduino ou sur ton NE555?

l'entrée du 555 (ou la pin INT0 de l'arduino) se câble en direct entre le collecteur du transistor et la résistance qui va au +5V, c-à-d sur J2.

catsur:
Dernière question un peu plus terre à terre, qu'appelle-tu du fil telecom?

C'est un fil mono brin (rigide) utilisé dans les paires télécomm, en général du 0.5mm². c'est un fil idéal pour nos câblages sur bread-board, que l'on peut trouver par kilos si on connait quelqu'un qui en utilise professionnellement (un monsieur des télécoms quoi...). on le trouve par paire dans des gaines blanches ou grises, j'avais la chance d'avoir papa chez FT R&D, donc je dois avoir une centaine de mètres de 64 paires... de quoi câbler sur quelque siècles...

Bon courage!

Super_Cinci:

catsur:
J'ai trois questions

pour l'instant... :wink:

Donc me revoilà!

Merci pour ta réponse, désolé je mets du temps à répondre, mais en fait la semaine j'ai pas trop le temps de penser à tout ça.

Donc, je pensais à un truc : si je branche J2 directement sur une entrée de l'arduino, et que je fais un programme dans mon loop du genre :

  • Relever le timer
  • Un while pour dire "tant que J2 est à 0 je reste là"
  • Quand J2 est à 1, je relève le timer (je pense faire une boucle ici pour attendre 10 étincelles pour avoir une valeur plus précise)
  • Je fais la différence sur le timer pour connaitre l'interval entre les deux étincelles
  • Et hop je connais mon régime moteur!

Ce n'est pas plus simple? :roll_eyes: Bien que je remette pas en cause ton programme bien sûr mais je préfère faire quelque chose que je comprenne car il faut que je progresse en écrivant mes propres programmes!