Sécurité lors du démarrage moteur

Bonjour à tous !

Je vous explique mon projet que j'ai commencé à coder mais il doit y avoir des erreurs du à mon manque de connaissance ( j'apprends doucement....)

Je souhaiterai allumer un moteur avec un bouton pressoir et qu'il se mette en marche à la seconde pression avec un intervalle de moins de deux seconde afin que si on appuie par erreur il ne se mette pas en route. Le moteur doit s'arrêter avec un contacteur fin de course.

Ce montage est monté sur un tour. Je fais le perçage manuellement et je voudrais que l'outil revienne à la position initiale avec une aide électrique.

J'ai mis des explications dans le code mais je pense que j'ai mal paramètré millis() et la syntaxe ainsi que la logique ne doit pas être correcte..... mais c'est un début qui demande qu'à être amélioré. Je me suis aidé des tutos
sur locoduino mais je dois pas avoir fait tout correctement.....

``Merci pour vous conseils et aide ! :wink: :slight_smile:


```cpp
#include <Arduino.h>

int Bouton = 3;   // bouton pressoir
int Rmoteur = 4;  // relais moteur
int fdc = 5;      // contacteur fin de course
unsigned long HeureActuelle = 0;
unsigned long HeurePrecedente = 0;
unsigned long Intervalle = 2000;
byte EtatBouton = HIGH;  // bouton pressoir ouvert (non appuyé)

void setup() {

  pinMode(Bouton, INPUT_PULLUP);
  pinMode(Rmoteur, OUTPUT);
  pinMode(fdc, INPUT_PULLUP);
}

void loop() {

  // on appuie une première fois mais cela n'allume pas le moteur
  while (digitalRead(Bouton) == LOW); // bouton pressoir fermé (appuyé)
  digitalWrite(Rmoteur, LOW);  // Relais moteur ouvert moteur éteint

  // on demarre le chrono
  HeureActuelle = millis();

  // si le bouton pressoir est appuyé mais que l'intervalle est superieur à 2s le relais reste ouvert et le moteur reste arrêté
  if (EtatBouton == LOW && (HeureActuelle - HeurePrecedente) > Intervalle) {
    EtatBouton = LOW;
    digitalWrite(Rmoteur, EtatBouton);
    HeurePrecedente = HeureActuelle;
  }

  // si le bouton pressoir est appuyé mais que l'intervalle est inferieur à 2s le relais se ferme et le moteur demarre
  else if (EtatBouton == LOW && (HeureActuelle - HeurePrecedente) < Intervalle) {
    EtatBouton = HIGH;
    digitalWrite(Rmoteur, EtatBouton);
    HeurePrecedente = HeureActuelle;
  }

  //lorsque contacteur fin de course est appuyé le relais coupe le moteur
  while (digitalRead(fdc) == LOW)
    ;
  digitalWrite(Rmoteur, LOW);
}

Bonjour guillaume07

Pour ce genre de "surveillance", un double click, tu te simplifiera le programme en utilisant une bibliothèque comme OneButton,


qui comprend une fonction double-click.

Cordialement
jpbbricole

Bonjour,

C'est bien quand on débute de chercher à faire des petites applications sans forcément utiliser une bibliothéque, comme tu l'as fait avec le BP.

Je ne suis pas un pro du code
Je reléve beaucouo d'erreurs dans ton code, des erreurs de syntaxe et un manque de définition je crois au niveau de ton algorythme.

Tu n'as pas définit dans le setup l'état initiale du relais.

Tu a fait une erreur avec le "WHILE".

Tu as écris:

while (digitalRead(Bouton) == LOW); // bouton pressoir fermé (appuyé)
  digitalWrite(Rmoteur, LOW);  // Relais moteur ouvert moteur éteint

  // on demarre le chrono
  HeureActuelle = millis();
...

Tu as oublié de mettre entre { .... } les actions à répeter "tant que" (while) la condition entre (...) est vraie.

Autre remarques:

-Tu as définit ton entrée bouton en Input_Pullup, mais sais tu quel est l'état du BP quand il n'est pas appuyé, Ouvert ou Fermé?
-L'as tu branché entre une Input et GND?
-Du fait de leur action mécanique, les BP ont des rebonds qui fait que lorsqu'on appuie dessus le contact élec du BP rebondit pendant un certain temps trés bref (quelques ms) entre Fermé/Ouvert.
C'est gênant quand on attend un double clique.

...

Si je puis le permettre, je te conseille donc de revoir les While, de faire quelques recherches sur les remédes simples contre les rebonds, et de te pencher sur le tuto disponible sur ce forum sur "La machine d'états" de J.M.L qui s'adapte parfaitement à tes besoins.

Et n'hésite pas à poser des questions.

1 Like

Super ! Merci beaucoup pour votre aide et conseils, je vais approfondir et essayer d'améliorer cela.... :slight_smile: :+1:

Guillaume

D'un point de vue sécuritaire, je pense qu'un appui long est plus sûr qu'un double clic car il a beaucoup moins de chance d'être accidentel. Des rebonds, des parasites peuvent être vus comme des doubles clics.

Bonjour jef59

Non, c'est le contraire, "l'idée Arduino" est justement l'usage de toute une collection de bibliothèques afin de simplifier la programmation. Dans ce cas, pour contrôler un double click ou, comme le préconise @fdufnews un click long.

Ou moyen plus actuel, poser la question à l'IA.

Cordialement
jpbbricole

Bonjour,

Pour un "clique" ou appui long, ce qui simplifie énormément le probléme, pas besoin je trouve de bibliothéque.

Et quoi qu'il en soit, même si on recours à l'IA et aux bib., il faut déja avoir une idée précise de ce qu'on attend pour poser la bonne question.

Donc je trouve que au départ c'est bien de se creuser un peu les méninges sur des cas simples.

Du moins c'est ce que je conseille tout simplement.

1 Like

Salut,

J'ai utilisé la bibliothèque OneButton et cela facilite Enormément la tâche.

J'ai utilisé la led 13 pour facilité la simulation.

Donc j'arrive à allumer la led avec un double click par contre étant donné que je souhaite l'éteindre avec le contacteur fin de course, celui-ci n'a aucune action.

Je pense que la syntaxe de fonction while ne doit pas être correcte, car si je la remplace par un delay, la led s'allume et s'éteint. Pourtant j'ai regardé dans un autre projet où j'ai des fonctions while et la sythaxe me parait correcte.

Merci pour votre aide, ça permet d'évoluer ! :slight_smile:


```cpp
#include <Arduino.h>
#include <OneButton.h>

OneButton bouton(A1, false);
int fdc = 5;

void setup() {

Serial.begin(115200);
bouton.attachDoubleClick(doubleclick);
pinMode(13, OUTPUT);
pinMode(5, OUTPUT);

}

void loop() {

bouton.tick();
delay(10);
}

void doubleclick() {
  
digitalWrite(13, HIGH);

while (digitalRead (fdc)==LOW);
digitalWrite(13, LOW);
}



Bonjour guillaume07

C'est évident, les bibliothèque sont ce qui permet "d'aller plus loin" sans trop se prendre la tête, c'est un des gros truc du monde Arduino à utiliser sans modération :wink:.
Dans ton programme il y a plusieurs choses.

L'initialisation de la pin du FDC:
pinMode(5, OUTPUT);
FDC est une entrée donc c'est:
pinMode(3, INPUT_PULLUP);
Si PULLUP, quand le FDC est ON on lit LOW, comme tu l'as bien fait.

La lecture du PDC:
Tu as mis ça dans l'événement du double-click, ça n'est pas la bonne place. En effet, une fois le dfouble-click lu et son action exécutée, son rôle est terminé. Ensuite, il faut scruter en permanence le contact du FDC et ceci se fait dans loop().

void loop() {
	bouton.tick();

	if (digitalRead(5) == LOW)
	{
		digitalWrite(13, LOW);
	}
}

A+
Cordialement
jpbbricole

Bonjour,

C'est dommage, tu contourne la difficulté de la syntaxe du "While" qui ici est mal écrit par un "If".

Bonjour jef59

Les quelles, mise à part un problème de copier/coller ```cpp

Il n'y a pas des actions mais une action donc les accolades ne sont pas nécessaires.

A quoi sert un While, pour lire "au vol" un contact ?
Si c'est juste pour faire une théorie sur le While, autant la placer à bon escient et que se soit complet.

Cordialement
jpbbricole

Hello,

Oui en effet j'avais pas vu l'erreur de déclaration du fdc... Je maîtrise cela pourtant .... :sweat_smile:

Voici la version que j'ai écrite et qui fonctionne parfaitement comme je le souhaite:


```cpp
#include <Arduino.h>
#include <OneButton.h>

OneButton bouton(A1, false);
int fdc = 5;

void setup() {

Serial.begin(115200);
bouton.attachDoubleClick(doubleclick);
pinMode(13, OUTPUT);
pinMode(5, INPUT_PULLUP);
}
void loop() {

bouton.tick();
delay(10);
}

void doubleclick() {
  
digitalWrite(13, HIGH);
while (digitalRead (fdc)==HIGH);
digitalWrite(13, LOW);
}



Merci à tous pour l'aide ! :) :muscle: :trophy:

Bonjour guillaume07

Ta solution fonctionne, mais elle a un petit défaut, du fait de:
while (digitalRead (fdcPin)==HIGH);
ton programme est complètement bloqué, tant que FDC n'est pas atteint. Si tu ne veux rien faire d'autre, pas de problème, par contre, si, pendant le retour tu veux faire quelque chose, il est préférable d'utiliser l'option :

	if (digitalRead(fdcPin) == LOW)
	{
		digitalWrite(moteurRelaisPin, LOW);
	}

dans loop()

Dernière petite remarque, dans l'écriture de ton programme, nomme tes pin utilisées en les déclarant au début, ça facilite grandement la lecture du code, un exemple:

#include <Arduino.h>
#include <OneButton.h>

const int boutonPin = A1;
const int fdcPin = 5;
const int moteurRelaisPin = 13;

OneButton bouton(boutonPin, false);

void setup() {

	Serial.begin(115200);
	
	bouton.attachDoubleClick(doubleclick);
	pinMode(moteurRelaisPin, OUTPUT);
	pinMode(5, INPUT_PULLUP);
}
void loop() {

	bouton.tick();
	delay(10);
}

void doubleclick() {
	
	digitalWrite(moteurRelaisPin, HIGH);
	while (digitalRead (fdcPin)==HIGH);
	digitalWrite(moteurRelaisPin, LOW);
}

Cordialement
jpbbricole

A la fois, c'est dommage que vous utilisiez l'IA pour assoir vos explications.

Premiérement parce que l'IA dit entre autre:
Voici quelques exemples de situations où utiliser while peut être approprié :
1. Attendre une condition spécifique

Si vous voulez que le programme attende jusqu'à ce qu'une condition spécifique soit vraie avant de continuer, un while est idéal. Par exemple, attendre qu'un bouton soit pressé

cpp

int buttonPin = 2;

void setup() {
  pinMode(buttonPin, INPUT);
}

void loop() {
  // Attendre que le bouton soit pressé
  while (digitalRead(buttonPin) == LOW) {
    // Rien ne se passe tant que le bouton n'est pas pressé
  }
  
  // Le programme continue une fois le bouton pressé
  // Insérer les actions après la pression du bouton
}

Dans cet exemple, avec acollades, proposé par l'IA (Chat GPT), on attend qu'un bouton soit pressé.
Comme dans le cas de Guillaume.

La question posée au Chat était:
"Arduino, quand utiliser while?

Bon d'un autre côté, l'IA dit aussi:

"ChatGPT peut faire des erreurs. Envisagez de vérifier les informations importantes."

Il ne faut donc pas être technico-rigide et ne marcher que selon ce que dit l'IA.

Encore, une fois, tu n'a pas compris grand chose, comme tu le répète souvent, tu n'est pas un pro du code, mais tu peux revendiquer celui être un pro de la polémique.

+1 avec JPB

un while, comme un delay doit être utilisé avec précaution sur un Arduino, surtout que la fonction loop est déjà dans une boucle while.
Donc autant l'utiliser et ne pas bloqué l'Arduino si ce n'est pas nécessaire.

Ici une des données du probléme est:

Guillaume a tenté de résoudre ce probléme avec l'instruction While.

Dans son cas, où il n'a rien à faire entre le premier appui du BP et le second appui s'il a lieu avant 2 secondes (ormis filtrer les éventuels rebonds), il n'y a il me semble aucune raison technique rendant impossible ou innaproprié l'usage du While (ni même du delay).

Donc je suggerais à Guillaume de tenter, pour son apprentissage de mener â bien sa tentative avec un While.

De ton côté toi @jpbbricole tu suggére l'usage des bibliothéques, de l'AI et du IF.

Donc je suis tes conseils, j'interoge entre autre l'AI.

AI, avec Arduino, quand utiliser While?

Réponse, exemple à l'appui:
Si vous voulez que le programme attende jusqu'à ce qu'une condition spécifique soit vraie avant de continuer, un while est idéal. Par exemple, attendre qu'un bouton soit pressé

Ce n'est pas en partie ce que recherche Guillaume?.

Tant que le BP n'est pas appuyé une deuxiéme fois ET que le temps est inférieur à 2 seconde:
Ne rien faire (laisser le moteur à l'arrêt)

Ta réponse n'est pas une bonne réponse à mes yeux, ce n'est pas une réponse technique, c'est dommage, ce n'est pas moi qui polémique.

Explique moi, ou explique nous plutôt pourquoi ce n'est pas possible d'utiliser While. (et pourquoi l'AI ne se trompe pas si elle le fait).
Ou pourquoi c'est mieux d'utiliser IF.

Tewal, lui, nous dit

Donc selon lui, pro du code, c'est possible, avec précautions.

C'est une réponse techniquement plus éclairante.

Là par contre, je ne suis pas sûr d'avoir compris.

De mon côté, promis, je posterais mon code avec While (je ne l'ai pas écris encore).

Voilà le main() qui n'est pas visible de l'utilisateur. On voit que loop() est placée dans une boucle infinie. Ce n'est pas un while mais un for, dans le principe cela ne change pas grand chose. loop() est appelée en permanence.

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}



Maintenant, et cela s'adresse à tout le monde, ces polémiques à répétition commencent à devenir lassantes. On échange et on est pas obligatoirement tous d'accord, et c'est normal, mais depuis quelque temps cela part un peu trop rapidement en vrille et finit le plus souvent en querelles d'égo. Il faudrait un peu calmer le jeu parce que sinon on va faire fuir tout le monde.

4 Likes

Bonjour à tous,

Tout d'abord un grand merci à tout le monde pour le temps que vous avez pris pour m'apporter de l'aide. Je joins le code qui me convient et si cela peux aider quelqu'un d'autre. Mon but est de progresser et d'arriver à faire fonctionner le code pour qu'il corresponde au fonctionnement de la machine pour lequel je l'ai conçu. Il est certes perfectible, il le sera toujours d'ailleurs, donc à mon échelle je trouve que cela est déjà très bien qu'il fonctionne comme je le souhaite. Plus tard si je deviens meilleur et que le projet demande plus de rigueur et de subtilité il faudra chercher plus de perfection. En attendant on est la pour s'amuser et se rendre service donc continuons ainsi. Rien ne vaut le partage Humain avec de vraies personnes, je suis vraiment pas attirer par l'IA .... Bonne journée à vous ! :wink: Peace :v: :sunflower:


```cpp
#include <Arduino.h>
#include <OneButton.h>

OneButton bouton(A1, false);
int fdc = 5;
int Rmoteur = 4;

void setup() {

Serial.begin(115200);
bouton.attachDoubleClick(doubleclick);
pinMode(fdc,INPUT_PULLUP);
pinMode(Rmoteur,OUTPUT);
}

void loop() {

bouton.tick();
delay(10);
}

void doubleclick() {
  
digitalWrite(Rmoteur, HIGH);
while (digitalRead (fdc)==LOW);
digitalWrite(Rmoteur, LOW);
}



2 Likes

Tu as complétement raison, si ton code te conviens, il n'est pas question de te le faire changer.
Par contre pour ne pas induire en erreur et faire perdre du temps à d'autre personne qui utiliserait ton code, il est bon d'alerter sur le fait qu'il n'est pas recommander de faire des attentes actives à moins de bien comprendre ce que l'on fait.
Il n'est pas non plus du tout recommander non pas faire une attente active mais un long traitement dans un évènement.

Donc le message n'est pas il faut faire comme ci ou comme ça, ni même la seul méthode est celle-ci.
Le message est simplement qu'il faut faire attention et qu'une des solutions possibles est de ne pas bloquer le déroulement du programme, si cela n'est pas absolument nécessaires.

C'est quelque chose que l'on répété souvent, la problématique rencontré et pendant l'élaboration d'un programme et donc certain choix peut entrainer un blocage plus tard.

Donc voila il n'y pour moi pas de polémique à avoir, chacun code suivant à sa façon, mais il est bon de savoir des problématiques éventuels de ses choix.