Effectuer une action qu'une seule fois dans le loop() ?

Bonjour et bonne fête 8), après moult recherche, j'en arrive a la conclusion que c'est la jungle dans l'information, et que par conséquent je n'ai pas réussi a trouver ce que je cherchais...

Donc pour faire claire et ne pas trop vous faire perdre du temps, voilà ce que je veut :

Lecture de la valeur de ma photorésistance

Si elle dépasse 500
Alors actionner le moteur dans le sens horaire, une seul fois pendant X secondes puis le moteur stop jusqu'à au prochain changement d'état.
Sinon si elle ne dépasse pas 500
Alors actionner le moteur dans le sens anti-horaire une seule fois pendant X secondes puis le moteur stop jusqu'à au prochain changement d'état.

Le but étant de contrôler le moteur avec une lampe
Si ça reste allumé le moteur ouvre une trappe.
Si ça s'éteint il la ferme.

J'ai donc réussis a pwm le moteur pour avoir la longueur d'action que je souhaitais, malheureusement le moteur tourne en boucle...

const int monter = 2; // connecte au pin 7 du H-bridge
const int descendre = 3; // connecte au pin 2 du H-bridge
const int onOff = 9;   // connecte au pin 1 du H-bridge
int capteur1 = A0; // Capteur de lumière
int lum1 = 0; 


void setup()
{
  pinMode(monter, OUTPUT);
  pinMode(descendre, OUTPUT);
  pinMode(onOff, OUTPUT);
  digitalWrite(monter,LOW);
  digitalWrite(descendre, LOW);
} 
void loop()
{          
  lum1 = analogRead(capteur1); // lecture de la valeur du capteur1. 

  if (lum1 > 500)// Si lecture est supérieur à 500 le moteur monte en accélérant.
    { 
      digitalWrite(monter, HIGH);
      digitalWrite(descendre, LOW);
      MoteurAccelerationPWM();
    }
  
  if (lum1 < 500) // Si lecture est inférieur a 500 le moteur descend en ralentissant.
    {
    digitalWrite(monter,LOW);
    digitalWrite(descendre, HIGH);
    MoteurDescelerationPWM();
    }
}

void MoteurAccelerationPWM()
{
  // Acceleration
  for( int i = 80; i<= 90; i++ )
  {
    analogWrite( onOff, i );
    delay(50); // delay pour avoir un progression
    
  }
}

void MoteurDecelerationPWM()
{
  // Deceleration
  for( int i = 90; i>=80; i-- )// for (déclaration valeur instruction (ici, i = 31% pwm); while (tant que i est plus grand que 0; alors i décrémente)
  {
    analogWrite( onOff, i );
    delay(50); // delay pour avoir un progression
    
  }
}

Je pense que le problème ne vient pas de mes deux fonctions "MoteurDecelerationPWM()" et "MoteurAccelerationPWM()" mais du loop qui part du principe que si la lumière On/Off alors effectue cette action en boucle...
Donc comment faire pour que la lecture déclenche l'action qu'une seule fois, mais qu'un changement d'état la fasse repartir ?

bonjour,
tu mets une variable en plus qui prend une valeur style

int valid = 0;
....
....
.....
if (lum1 > 500 && valid == 0)
{ 
      digitalWrite(monter, HIGH);
      digitalWrite(descendre, LOW);
      MoteurAccelerationPWM();
valid = 1;
    }
  
  if (lum1 < 500 && valid ==1 ) // Si lecture est inférieur a 500 le moteur descend en ralentissant.
    {
    digitalWrite(monter,LOW);
    digitalWrite(descendre, HIGH);
    MoteurDescelerationPWM();
valid = 0;
    }

infobarquee:
bonjour,
tu mets une variable en plus qui prend une valeur style

int valid = 0;

....
....
.....
if (lum1 > 500 && valid == 0)
{
      digitalWrite(monter, HIGH);
      digitalWrite(descendre, LOW);
      MoteurAccelerationPWM();
valid = 1;
    }
 
  if (lum1 < 500 && valid ==1 ) // Si lecture est inférieur a 500 le moteur descend en ralentissant.
    {
    digitalWrite(monter,LOW);
    digitalWrite(descendre, HIGH);
    MoteurDescelerationPWM();
valid = 0;
    }

Merci, ça ne fonctionner pas comme tel, la boucle ce bouclée toujours, j'ai donc modifié mes fonctions pour donner ça :

void MoteurAccelerationPWM()
{
  // Acceleration
  for( int i = 80; i<= 90; i++ )
  {
    analogWrite( onOff, i );
    delay(50); // delay pour avoir un progression
    digitalWrite(onOff, LOW); // arrête le moteur a la fin de l'action
  }

Sans le digitalWrite(onOff, LOW); a la fin, ça tourne en boucle :sweat_smile:

si la lumière varie en permanence entre 499 et 501, c'est normal.
soit tu mets une valeur plus petite et une plus grande 400 - 550
soit tu mets hysteresis afin de palier au passage permanent entre chaque valeur.

mais le fait de mettre digitalWrite(onOff, LOW); dans ta boucle for, c'est pas le top :wink:
à chaque incrémentation, ca met le onoff à low
mets le après ta boucle

void MoteurAccelerationPWM()
{
  // Acceleration
  for( int i = 80; i<= 90; i++ )
  {
    analogWrite( onOff, i );
    delay(50); // delay pour avoir un progression
  }
    digitalWrite(onOff, LOW); // arrête le moteur a la fin de l'action
}

ou tu le mets juste après l'appel dans ton if

if (lum1 > 500 && valid == 0)
{ 
      digitalWrite(monter, HIGH);
      digitalWrite(descendre, LOW);
      MoteurAccelerationPWM();
valid = 1;
    digitalWrite(onOff, LOW); // arrête le moteur a la fin de l'action
    }
  
  if (lum1 < 500 && valid ==1 ) // Si lecture est inférieur a 500 le moteur descend en ralentissant.
    {
    digitalWrite(monter,LOW);
    digitalWrite(descendre, HIGH);
    MoteurDescelerationPWM();
valid = 0;
    digitalWrite(onOff, LOW); // arrête le moteur a la fin de l'action
    }

mais ca m'étonnerait que ta valeur puisse être égale à 500 très longtemps :wink:

infobarquee:
si la lumière varie en permanence entre 499 et 501, c'est normal.
soit tu mets une valeur plus petite et une plus grande 400 - 550
soit tu mets hysteresis afin de palier au passage permanent entre chaque valeur.

mais le fait de mettre digitalWrite(onOff, LOW); dans ta boucle for, c'est pas le top :wink:
à chaque incrémentation, ca met le onoff à low
mets le après ta boucle

ou tu le mets juste après l'appel dans ton if

mais ca m'étonnerait que ta valeur puisse être égale à 500 très longtemps :wink:

En faite lumière ambiante les valeur oscille entre 100 et 200, avec la lampe à 30 cm ça monte directement a plus de 600, comme je suis plus près, les valeurs sont franchement au dessus de 500 et franchement en dessous de 500.

Je ne comprend pas ta phrase en gras par contre ?

OK, tu fais un test qui actionne une seule fois, donc à chaque fois que le test est validé, il faut attendre le changement d'état pour agir de nouveau.

En C,, attendre = while :

void loop(){
  valeur = analogRead(capteur1);

  if (valeur > 500){
    action_moteur(horaire);
    while (valeur > 500){  // tant que >500, boucler, tourner en rond.
      valeur = analogRead(capteur1);
    }
  } else {  // sous-entendu "pas >500"
    action_moteur(anti_horaire);
    while (!(valeur > 500)){  // tant que pas >500, boucler, tourner en rond.
      valeur = analogRead(capteur1);
    }
  }
}

Ceci dit, ça marche, mais c'est pas beau. Je te propose de trouver et nous dire pourquoi c'est pas beau, un petit exercice entre deux oeufs en chocolat ne te fera pas de mal :wink: Ca t'orientera peut-être vers une autre façon de gérer la chose.

Super_Cinci:
OK, tu fais un test qui actionne une seule fois, donc à chaque fois que le test est validé, il faut attendre le changement d'état pour agir de nouveau.

En C,, attendre = while :

void loop(){

valeur = analogRead(capteur1);

if (valeur > 500){
   action_moteur(horaire);
   while (valeur > 500){  // tant que >500, boucler, tourner en rond.
     valeur = analogRead(capteur1);
   }
 } else {  // sous-entendu "pas >500"
   action_moteur(anti_horaire);
   while (!(valeur > 500)){  // tant que pas >500, boucler, tourner en rond.
     valeur = analogRead(capteur1);
   }
 }
}


Ceci dit, ça marche, mais c'est pas beau. Je te propose de trouver et nous dire pourquoi c'est pas beau, un petit exercice entre deux oeufs en chocolat ne te fera pas de mal ;) Ca t'orientera peut-être vers une autre façon de gérer la chose.

Je vais regarder et y réfléchir, mais a première vue... :cold_sweat:

Sinon voilà ce que donne mon code actuel:

En faite, le moteur CC est pas fait pour ça :sweat_smile:
Je vais re-essayer avec un PAP :.

Bizounours:
En faite, le moteur CC est pas fait pour ça
Je vais re-essayer avec un PAP :.

Si le moteur CC est fait pour ça mais il faut des détecteurs qui indiquent si la guillotine est en haut ou en bas pour arrêter le moteur au bon moment.

Le mien va plus loin que prévu uniquement avec l'inertie du bout de carton qui tombe :grin:

Sinon j'en ai de 18v (d'une imprimante) mais le transfo de l'imprimante fait 18 ou 32v mais je n'ai pas de doc sur le moteur :confused:

C'est un moteur C9000-6005
1030048
3J0821 86
Il vient d'une imprimante HP Deskjet F2280
EDIT, je vient de tester, sous 18v, il tourne nickel, et en mesure A je trouve 0.08 A soit 80mA si je ne me trompe pas ?
Il consomme donc autant que le moteur d'avant qui étais pourtant 3 fois plus petit...

Super_Cinci:
OK, tu fais un test qui actionne une seule fois, donc à chaque fois que le test est validé, il faut attendre le changement d'état pour agir de nouveau.

En C,, attendre = while :

void loop(){

valeur = analogRead(capteur1);

if (valeur > 500){
    action_moteur(horaire);
    while (valeur > 500){  // tant que >500, boucler, tourner en rond.
      valeur = analogRead(capteur1);
    }
  } else {  // sous-entendu "pas >500"
    action_moteur(anti_horaire);
    while (!(valeur > 500)){  // tant que pas >500, boucler, tourner en rond.
      valeur = analogRead(capteur1);
    }
  }
}


Ceci dit, ça marche, mais c'est pas beau. Je te propose de trouver et nous dire pourquoi c'est pas beau, un petit exercice entre deux oeufs en chocolat ne te fera pas de mal ;) Ca t'orientera peut-être vers une autre façon de gérer la chose.

Après mainte réflexion je ne vois pas, mise a part que du coup ça spam la lecture du capteur ?

Je me permet de Up, j'ai donc essayer avec un moteur plus gros, et il s'avère qu'à cause de la ficelle (certainement) le système est loin d'être précis, j'ai acheter du carton plume, je vais essayer de fabriquer des engrenages voir si c'est plus précis !

Le résultat :

Sinon pour Super_Cinci, c'est pas propre parce que tant qu'on atteint pas la condition ça ne sort pas de la boucle et ça nous bloquerais pour une autre action éventuelle ?