Problème deroulement du code (basic)

Bonjour,
Je m’excuse d’avance pour la simplicité de mon problème.
Je cherche a faire un compte tour pour un moteur et j’ai opté pour une version semi-mécaniques. j’ai un disque fixé a l’axe de mon moteur avec une encoche en v sur ce disque. Il y a un interrupteur a lamelle, qui est fixe et qui est pressé (fermé) . L’interrupteur ne se libère ( ouvert) que quand il est en face de l’encoche du disque, une fois par tour de moteur.
Mon problème c’est que j’ai besoin que mon code arrête le moteur quand l’interrupteur est ouvert, qu’un delais se passe et que le moteur reparte jusqu’à la prochaine fois ou l’interrupteur s’ouvre.
Jusque la j’en suis la.





const int buttonPin = 13;     // the number of the pushbutton pin
const int motor =  7;      // the number of the motor pin


int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the motor pin as an output:
  pinMode(motor, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT_PULLUP);

}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is free. If it is, the buttonState is LOW:
  if (buttonState == LOW) {
    // turn motor off:
    digitalWrite(motor, HIGH);
    delay(1000);
    // turn motor on:
    digitalWrite(motor, LOW);
    delay(1000);

  }
   // turn motor on:
  digitalWrite(motor, LOW);

}

Et mon problème c’est que jusque là. Le moteur s’allume bien quand l 'interrupteur est fermé, il s’éteint quand l’interrupteur est ouvert mais il repart pas après le délais quand l’interrupteur est ouvert.
Es ce que le code est mal écrit? Merci d’avance pour votre aide

Combien de temps prends un tour ?

Tu testes ça avec un bouton poussoir ou avec l’interrupteur réel ?
Dans ce dernier cas, j’ai l’impression que quand le moteur s’arrête, l’interrupteur reste ouvert même lorsque le moteur repart et donc il s’arrête aussitôt. Tu n’en sors jamais. Il faudrait laisser le moteur tourner suffisamment (sans lire l’interrupteur) pour laisser le temps à l’interrupteur de se fermer.

Mais peut-être que je n’ai pas bien compris le fonctionnement…

Il y a quand même une attente d’une seconde après le redémarrage… tout dépend de si ça suffit

Un tour prend 3 secondes.
L’interrupteur c’est un interrupteur a lamelle ou interrupteur de fin de course.
(un bouton poussoir avec une lamelle dessus ).
Es ce que j’ai un moyen de vous faire voir une photo sur le forum?

J’ai augmenter le temps d’arret auparavent pour essayer ( 10s), sans resultat.
C’est comme si dans If il n’executer que la premier instruction
digitalWrite(motor, HIGH);

Es ce que le code vous semble correct? ou es ce que je dois tenter une autre approche?

Ajoute dans le setup
Serial.begin (115200);
Et dans ton if avant chaque digitalWrite
Serial.writeln("digitalWrite high");
Ou low.

Puis ouvre la console série de l’IDE, règle la sur un débit de 115200 baud, et lance ton code. Tu verras s’il exécuté tous les digitalWrite.

Je pense qu’il faudrait faire afficher l’état de buttonState, peut-être y-a-t-il un comportement imprévu. Éventuellement en faisant afficher à coté la valeur de millis() pour avoir l’information temps associée à l’état du contact.
Pour ne pas saturer le terminal peut-être mettre un delay(100) dans la boucle.

essayez avec ce code

j’ai mis la commande moteur sur la pin 7 et le fin de course sur la pin 2
ouvrez le moniteur série à 115200 bauds
dites nous ce qu’il s’affiche (dites nous aussi exactement comment tout cela est branché et alimenté)

const byte pinEndStop = 2;
const byte pinMoteur =  7;

enum : byte {enArret, enFonction, enPause, enRedemarrage} etatMoteur = enArret;
unsigned long debutAction;

void activerMoteur() {
  Serial.println(F("activation moteur"));
  digitalWrite(pinMoteur, LOW); // on lance le moteur
  etatMoteur = enFonction;
}

void pauseMoteur() {
  Serial.println(F("pause moteur"));
  digitalWrite(pinMoteur, HIGH); // on arrête le moteur
  debutAction = millis();
  etatMoteur = enPause;
}

void redemarrerMoteur() {
  Serial.println(F("redémarrage moteur"));
  digitalWrite(pinMoteur, LOW); // on lance le moteur
  debutAction = millis();
  etatMoteur = enRedemarrage;
}

void gestionMoteur() {
  switch (etatMoteur) {
    case enArret: activerMoteur(); break; // on le lance

    case enFonction: // si le endStop est appuyé on passe en pause
      if (digitalRead(pinEndStop) == LOW) pauseMoteur();
      break;

    case enPause: // si le temps de pause est dépassé on redémarre (et on laisse un peu de temps avant de vérifier le endStop)
      if (millis() - debutAction >= 1000) redemarrerMoteur(); // 1s de pause
      break;

    case enRedemarrage: // si le temps du redémarrage est passé, on est en fonctionnement nominal
      if (millis() - debutAction >= 1000) etatMoteur = enFonction; // 1s avant de revérifier le bouton, largement le temps de le quitter
      break;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(pinEndStop, INPUT_PULLUP);
  pinMode(pinMoteur, OUTPUT);
}

void loop() {
  gestionMoteur();
}
1 Like

JML, avant tout merci beaucoup!

J’ai lancé le code
et étrangement quand l’interrupteur est fermé, il y a bien une alternance moteur activé/arret (visible sur le moniteur).
Mais quand il est ouvert ( ce que je cherche a faire) c’est pas le cas.

Pour le montage: la fin de course est directement brancher ground et pin2
le moteur est activé par un relais:
le relais est alimenté par l’arduino 5V et ground
la pin 7 active le relais
et le moteur alimenter indépendamment en
12V

Je viens juste de changer les valeurs HIGH/ LOW.
Fabuleux!
Tout fonctionne comme je me l’étais imaginé.
Merci Enormement JML!

Je voudrais vous demander une dernière chose qui dépasse légèrement le cadre de l’ouverture de se post.
Je souhaitais pouvoir avoir un temps de pause différent une fois sur deux.
Et je vous avoue que je suis un peu dépasser par le code que vous avez fait.
Es ce que vous pourriez m’expliquer comment m’y prendre?

Le temps de pause est défini ici


case enPause: // si le temps de pause est dépassé on redémarre (et on laisse un peu de temps avant de vérifier le endStop)
      if (millis() - debutAction >= 1000) redemarrerMoteur(); // 1s de pause
      break;

Il faut mettre une variable à la place de 1000 et la faire alterner à chaque mise en pause (donc par exemple dans la fonction en pause vous échangez la valeur qui sera utilisée)

Je bloque un peu. J’ai créer la varible sous cette forme.

char tempsx = 0;
int tempspause;
      if ( tempsx >= 5) {
    tempspause = 10000;
    tempsx = 0;
  }
  else {
    tempspause = 1000;
  }

  tempsx = tempsx + 1;
case enPause: 

// si le temps de pause est dépassé on redémarre (et on laisse un peu de temps avant de vérifier le endStop)
if (millis() - debutAction >= tempspause) redemarrerMoteur(); // 1s de pause
break;

Blockquote

il me semble donc que ça devrait permettre qu’une fois sur 5 le temps de pause soit de 10s au lieu d’une mais je trouve pas la place adéquate dans le code pour créer la boucle qui additionne tempsx a chaque tour.
JML es ce que vous auriez une suggestion ou es ce que je m’y prend mal

je pensais à quelque chose comme cela:

const byte pinEndStop = 2;
const byte pinMoteur =  7;

const byte ALLUME = HIGH; // à adapter au montage
const byte ETEINT = LOW;
const byte APPUI = LOW;

enum : byte {enArret, enFonction, enPause, enRedemarrage} etatMoteur = enArret;
unsigned long debutAction;

const unsigned long pause1 = 1000; // 1s
const unsigned long pause2 = 3000; // 3s
unsigned long dureePause = pause1;

void activerMoteur() {
  Serial.println(F("activation moteur"));
  digitalWrite(pinMoteur, ALLUME); // on lance le moteur
  etatMoteur = enFonction;
}

void pauseMoteur() {
  Serial.println(F("pause moteur"));
  digitalWrite(pinMoteur, ETEINT); // on arrête le moteur
  debutAction = millis();
  etatMoteur = enPause;
}

void redemarrerMoteur() {
  Serial.println(F("redémarrage moteur"));
  digitalWrite(pinMoteur, ALLUME); // on lance le moteur
  
  // on alterne les durées de pause
  if (dureePause == pause1)
    dureePause = pause2;
  else
    dureePause = pause1;
  
  debutAction = millis();
  etatMoteur = enRedemarrage;
}

void gestionMoteur() {
  switch (etatMoteur) {
    case enArret: activerMoteur(); break; // on le lance

    case enFonction: // si le endStop est appuyé on passe en pause
      if (digitalRead(pinEndStop) == APPUI) pauseMoteur();
      break;

    case enPause: // si le temps de pause est dépassé on redémarre (et on laisse un peu de temps avant de vérifier le endStop)
      if (millis() - debutAction >= dureePause) redemarrerMoteur(); // pause variable gérée dans la fonction redemarrerMoteur
      break;

    case enRedemarrage: // si le temps du redémarrage est passé, on est en fonctionnement nominal
      if (millis() - debutAction >= 1000) etatMoteur = enFonction; // 1s avant de revérifier le bouton, largement le temps de le quitter
      break;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(pinEndStop, INPUT_PULLUP); // MONTAGE AVEC PULLUP INTERNE. LOW = APPUI
  pinMode(pinMoteur, OUTPUT);
}

void loop() {
  gestionMoteur();
}

la fonction redemarrerMoteur() va non seulement relancer le moteur mais aussi faire alterner la duree de pause (variable dureePause)

Merci encore!
Le code fonctionne parfaitement en alternant deux temps de pause différent.
Par contre j’ai essayé de rajouter un troisième temps différents, en suivant votre logique.

const unsigned long pause1 = 1000; // 1s
const unsigned long pause2 = 3000; // 3s
const unsigned long pause3 = 5000;//5s
unsigned long dureePause = pause1;

void redemarrerMoteur() {
  Serial.println(F("redémarrage moteur"));
  digitalWrite(pinMoteur, ALLUME); // on lance le moteur

  // on alterne les durées de pause
  if (dureePause == pause1)
    dureePause = pause2;

  if (dureePause == pause2)
    dureePause = pause3;
    
  else
    dureePause = pause1;

  debutAction = millis();
  etatMoteur = enRedemarrage;
}

et visiblement j’alterne uniquement entre pause 1 et pause 3, pause 2 semble “sauter” dans le code.
Es que je devrais plutôt privilégier dans ce cas une écriture sous forme de switch case ?
Je vous remercie encore pour votre aide j’ai bien conscience d’avoir largement dépassé le premier problème que vous avez résolu.

Ca semble fonctionner

const unsigned long pause1 = 1000; // 1s
const unsigned long pause2 = 3000; // 3s
const unsigned long pause3 = 5000;//5s
unsigned long dureePause = pause1;
void redemarrerMoteur() {
  Serial.println(F("redémarrage moteur"));
  digitalWrite(pinMoteur, ALLUME); // on lance le moteur

  // on alterne les durées de pause
  
switch(dureePause){
  
  case pause1:
  dureePause = pause2;
  break;
  
  case pause2:
  dureePause= pause3;
  break;

  case pause3:
  dureePause = pause1;
  break; 

  

}

il manquait un else… le premier if mettait dureePause à pause2 et le if juste après la passait à pause3 :slight_smile:

le switch est couteux dans ce contexte, vaut mieux rester sur des if

if (dureePause == pause1)   dureePause = pause2;
else if (dureePause == pause2)  dureePause = pause3; 
else  dureePause = pause1;
1 Like

Génial! Effectivement ça marche très bien!
Sincèrement merci beaucoup d’avoir pris le temps et d’avoir eut la patience.
J’en suis extrêmement reconnaissant.
En dehors de me permettre de réaliser le projet en cours, vous m’avez permis de clarifier quelques basiques qui me seront bien utiles par la suite.
Je vous souhaite une excellente journée, un peu j’espère comme celle que vous me permettez d’avoir.
Merci encore