Mesurer la durée d'une impulsion

Bonjour/Bonsoir
Nous sommes actuellement en classe Terminale et nous avons un projet à finaliser pour la fin de l'année en Sciences de l'Ingénieur. Nous avons décidé de réaliser un découpe ananas automatique. Pour cela nous utilisons un moteur à courant continu et une carte Arduino. Pour la sécurité du moteur, nous avons utilisé une résistance de 10? pour avoir une image du courant moteur. Le but étant de pouvoir arrêter le courant dans le moteur s'il dépasse un certain seuil pendant un certain temps: nous essayons de programmer cela avec l'arduino. Seulement nous n'arrivons pas à obtenir de temporisation, le moteur se coupe directement dès que le moteur dépasse ce seuil.

Voici notre code (non fonctionnel, sauf pour le bouton commandant le moteur) :

/*
Le circuit:
 * LED relié du PIN 3 à la masse (GND). 
 * Bouton poussoir relié de 5V au PIN 8 et un condensateur 10 nF en parallèle du bouton poussoir pour enlever les rebonds.
 * Une résistance de 10 kOhm (15 kOhm fonctionne aussi apparemment) reliée du PIN 8 à la masse (GND).
 
 */
 
const int mosfet = 3;    // PIN pour la commande du mosfet  (D3)
const int bouton = 8;    // PIN pour brancher l'interrupteur (D8)
const int moteur = 14;   // PIN pour brancher l'image du courant moteur à l'Arduino (A0)
int etat = 0;
int prev_etat = 0;
int prev_tension = 0;
int seuil_haut = 184;
int seuil_bas = 40;
int etat_temps1 = 0;
long temps1 = 0;


const int sortie1 = 9;   // PINs 9 à 11 permettent de simuler un fonctionnement du moteur
const int sortie2 = 10;  // PIN 9 = 0.1 V | PIN 10 = 0.5 V | PIN 11 = 1 V
const int sortie3 = 11;  // Pour modifier ces valeurs, se référer à (*)

void setup(){
 pinMode(mosfet, OUTPUT);
 pinMode(bouton, INPUT);
 pinMode(moteur, INPUT);
 
 pinMode(sortie1, OUTPUT);
 pinMode(sortie2, OUTPUT);
 pinMode(sortie3, OUTPUT);
}

void loop(){
  
  analogWrite(sortie1, 5); // (*) Le PINs sont dans l'ordre. La tension de 0 à 5V est codé sur 8 bits. C'est-à-dire : 0 = 0V et 255 = 5V. Pour coder une tension, se référer à la feuille Arduino que j'ai faite.
  analogWrite(sortie2, 30);
  analogWrite(sortie3, 51);
  
 int val = digitalRead(bouton);    // On lit la valeur du PIN correspondant au bouton.
 int tension = analogRead(moteur);
 
 if((val == HIGH) && (prev_etat == LOW)){  // Si le bouton est appuyé et que l'état précédent est bas (bouton non enfoncé), alors on change la valeur de etat.
   etat = 1 - etat;
   delay(10);                          // On attend 10 millièmes de secondes pour éviter les fausses détections dues à un bouton un peu vieux ou hasardeux.
 }
 
 prev_etat = val;                        // On enregistre l'état du bouton dans l'état précédent, on saura ainsi au prochain cycle si le bouton a été appuyé ou non.
 
 if((tension >= seuil_haut) && (prev_tension >= seuil_haut)){
   temps1 = millis();
 }
 else {

 }
 
 prev_tension = tension;
 
 if(etat == 0){
   digitalWrite(mosfet, LOW);           // Si la LED était allumée, on l'éteint, Si elle était éteinte, on l'allume.
 } 
 else {
   analogWrite(mosfet, 189); // 3.7 V en sortie
   
if((tension >= seuil_haut) && (( millis() - temps1) > 5000) && (temps1 != 0)) {
   etat = 0;
   temps1 = 0;
   prev_tension = tension;
  }
  else {}
  
 }

}

En espérant que vous pourrez nous apporter de l'aide !

Salut,

Ananasor:
Seulement nous n'arrivons pas à obtenir de temporisation, le moteur se coupe directement dès que le moteur dépasse ce seuil.

La je comprend pas, vous voulez quoi exactement ? Que le moteur s'arrête un certain temps ?

Ensuite pour être bien sûr : est-ce que vous avez bien compris que analogWrite() génère un signal PWM, donc des créneaux 0-5V et non une réelle tension fixe ?

pinMode(moteur, INPUT); => inutile pour une lecture analogique.

Sinon tu peux virer les "else {}", pas très utile xD

En fait, on lance le moteur en appuyant sur un bouton et on le coupe en rappuyant sur ce même bouton.
Lorsqu'on allume le moteur, ce dernier tourne (logique). Cependant, lorsqu'un problème est détecté, par exemple une sur-intensité signifiant que le moteur bloque ou bien qu'il démarre, d'où la nécessité de mesurer pendant combien de temps on a une sur-intensité (et donc une tension plus élevée que prévue). Ce que nous souhaitons, c'est donc de vérifier que "la tension est supérieure à une valeur A pendant X secondes" (alors on coupe le moteur). Idem lorsqu'on a une sous-intensité, le moteur tourne à vide, on souhaite donc vérifier que "la tension est inférieur à une valeur B pendant X' secondes" (alors on coupe le moteur).
Il y a également des tensions fixées sur les pins 9 à 11 afin de simuler la tension au bornes de la résistance de 10 Ohms.

En fait, on lance le moteur en appuyant sur un bouton et on le coupe en rappuyant sur ce même bouton.

Puisque tu parles de sécurité, c'est beaucoup plus sûr d'avoir un bouton spécifique pour l'arrêt.

Pour ton problème de surintensité, il faut échantillonner le temps lorsque ta surintensité est détectée

debutImax = millis()

et ensuite si la surintensité se poursuit vérifier si le temps actuel est supérieur à debutImax + TEMPS_MAX_ADMISSIBLE.

if (debutImax + TEMPS_MAX_ADMISSIBLE > millis){
   couper le moteur
}

Tout cela est à placer judicieusement dans ta boucle principale en veillant a y passer suffisamment souvent pour ne pas risquer de cramer ton moteur.
Il faut bien vérifier ton code pour t'assurer qu'il n'y a pas de fonctions bloquantes qui risqueraient de ruiner tes sécurités.

Dans notre cas, nous avons un cahier des charges à respecter, et le bouton de contrôle unique est un de nos critères ! Merci pour l'idée, nous allons essayer (d'ici quelques jours au plus tard). On vous tiens au courant en cas de soucis, encore merci !

Bonjour à tous, nous avons fais nos tests et cela fonctionne presque. On est proche du fonctionnement attendu, cependant, un problème demeure !
Notre moteur coupe bien au bout de X secondes (1,5 secondes pour nos tests) lorsqu'une surintensité est détectée. Toutefois, cela coupe même si la surintensité n'est plus au bout de X secondes. En d'autres termes, une surintensité de quelques millisecondes coupera le moteur automatiquement 1,5 secondes plus tard. Voici notre code :

/*
Le circuit:
 * LED relié du PIN 3 à la masse (GND). 
 * Bouton poussoir relié de 5V au PIN 8 et un condensateur 10 nF en parallèle du bouton poussoir pour enlever les rebonds.
 * Une résistance de 10 kOhm (15 kOhm fonctionne aussi apparemment) reliée du PIN 8 à la masse (GND).
 
 */
 
const int mosfet = 3;    // PIN pour la commande du mosfet  (D3)
const int bouton = 8;    // PIN pour brancher l'interrupteur (D8)
const int moteur = 14;   // PIN pour brancher l'image du courant moteur à l'Arduino (A0)
int etat = 0;
int prev_etat = 0;
int seuil_haut = 184;
int seuil_bas = 40;
int debutImax = 0;
int temps_max_seuil_haut = 1500;
int temps_max_seuil_bas = 3000;

const int sortie1 = 9;   // PINs 9 à 11 permettent de simuler un fonctionnement du moteur
const int sortie2 = 10;  // PIN 9 = 0.1 V | PIN 10 = 0.5 V | PIN 11 = 1 V
const int sortie3 = 11;  // Pour modifier ces valeurs, se référer à (*)

void setup(){
 pinMode(mosfet, OUTPUT);
 pinMode(bouton, INPUT);
 pinMode(moteur, INPUT);
 
 pinMode(sortie1, OUTPUT);
 pinMode(sortie2, OUTPUT);
 pinMode(sortie3, OUTPUT);
}

void loop(){
  
  analogWrite(sortie1, 5); // (*) Le PINs sont dans l'ordre. La tension de 0 à 5V est codé sur 8 bits. C'est-à-dire : 0 = 0V et 255 = 5V. Pour coder une tension, se référer à la feuille Arduino que j'ai faite.
  analogWrite(sortie2, 30);
  analogWrite(sortie3, 51);
  
 int val = digitalRead(bouton);    // On lit la valeur du PIN correspondant au bouton.
 int tension = analogRead(moteur);
 
 if((val == HIGH) && (prev_etat == LOW)){  // Si le bouton est appuyé et que l'état précédent est bas (bouton non enfoncé), alors on change la valeur de etat.
   etat = 1 - etat;
   delay(10);                          // On attend 10 millièmes de secondes pour éviter les fausses détections dues à un bouton un peu vieux ou hasardeux.
 }
 
 prev_etat = val;                        // On enregistre l'état du bouton dans l'état précédent, on saura ainsi au prochain cycle si le bouton a été appuyé ou non.
 
if((tension >= seuil_haut) && (debutImax == 0)) {
  debutImax = millis();
}

if((debutImax != 0) && ((debutImax + temps_max_seuil_haut) < millis())) {
  etat = 0;
  debutImax = 0;
}
 
 if(etat == 0){
   digitalWrite(mosfet, LOW);           // Si la LED était allumée, on l'éteint, Si elle était éteinte, on l'allume.
 } 
 else {
   analogWrite(mosfet, 189); // 3.7 V en sortie
 }

}

Des idées pour résoudre cet ultime problème ?

/*
Le circuit:
 * LED relié du PIN 3 à la masse (GND). 
 * Bouton poussoir relié de 5V au PIN 8 et un condensateur 10 nF en parallèle du bouton poussoir pour enlever les rebonds.
 * Une résistance de 10 kOhm (15 kOhm fonctionne aussi apparemment) reliée du PIN 8 à la masse (GND).
 
 */
 
const int mosfet = 3;    // PIN pour la commande du mosfet  (D3)
const int bouton = 8;    // PIN pour brancher l'interrupteur (D8)
const int moteur = 14;   // PIN pour brancher l'image du courant moteur à l'Arduino (A0)
int etat = 0;
int prev_etat = 0;
int seuil_haut = 184;
int seuil_bas = 40;
int debutImax = 0;
int temps_max_seuil_haut = 1500;
int temps_max_seuil_bas = 3000;

const int sortie1 = 9;   // PINs 9 à 11 permettent de simuler un fonctionnement du moteur
const int sortie2 = 10;  // PIN 9 = 0.1 V | PIN 10 = 0.5 V | PIN 11 = 1 V
const int sortie3 = 11;  // Pour modifier ces valeurs, se référer à (*)

void setup(){
 pinMode(mosfet, OUTPUT);
 pinMode(bouton, INPUT);
 pinMode(moteur, INPUT);
 
 pinMode(sortie1, OUTPUT);
 pinMode(sortie2, OUTPUT);
 pinMode(sortie3, OUTPUT);
}

void loop(){
  
  analogWrite(sortie1, 5); // (*) Le PINs sont dans l'ordre. La tension de 0 à 5V est codé sur 8 bits. C'est-à-dire : 0 = 0V et 255 = 5V. Pour coder une tension, se référer à la feuille Arduino que j'ai faite.
  analogWrite(sortie2, 30);
  analogWrite(sortie3, 51);
  
 int val = digitalRead(bouton);    // On lit la valeur du PIN correspondant au bouton.
 int tension = analogRead(moteur);
 
 if((val == HIGH) && (prev_etat == LOW)){  // Si le bouton est appuyé et que l'état précédent est bas (bouton non enfoncé), alors on change la valeur de etat.
   etat = 1 - etat;
   delay(10);                          // On attend 10 millièmes de secondes pour éviter les fausses détections dues à un bouton un peu vieux ou hasardeux.
 }
 
 prev_etat = val;                        // On enregistre l'état du bouton dans l'état précédent, on saura ainsi au prochain cycle si le bouton a été appuyé ou non.
 
if((tension >= seuil_haut) && (debutImax == 0)) {
  debutImax = millis();
}

if((debutImax != 0) && ((debutImax + temps_max_seuil_haut) < millis())) {
if(tension >= seuil_haut) {
  etat = 0;
}
  debutImax = 0;
}
 
 if(etat == 0){
   digitalWrite(mosfet, LOW);           // Si la LED était allumée, on l'éteint, Si elle était éteinte, on l'allume.
 } 
 else {
   analogWrite(mosfet, 189); // 3.7 V en sortie
 }

}

Il faut retester qu'au bout des 1,5s, la surintensité est toujours là.