Rotation de moteur à courant continu lors d'un décompte

Bonsoir,
J'aimerai mettre au point un montage et un programme qui permettent, grâce à un bouton poussoir, de lancer un moteur à courant continu pendant un temps que l'on a visionnée dans le moniteur série et que l'on à prédéfinit avec un potentiomètre. Le temps maximum est de 15 minutes et le moteur, une fois lancé doit augmenter progressivement dans sa vitesse avant de rester constant. Par exemple si on règle 10 minutes avec le potentiomètre en visionnant le moniteur série puis que l'on appuie sur le bouton poussoir, alors pendant les 10 prochaine minutes, le moteur doit augmenter progressivement de vitesse rapidement mais visiblement puis rester constant tout le reste du temps et enfin s'arrêter. Si l'on appuie une deuxième fois sur le bouton poussoir pendant que le moteur tourne, ce dernier doit s'arrêter.

const byte pinPotDuree = A0;
const int minPotDuree = 0;
const int maxPotDuree = 1023;
const byte boutonCommande = 3;
int VitesseMCC = 0;
int chrono;
const byte pinDuree = 6;
bool drapeau = false;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(boutonCommande, INPUT_PULLUP);
  pinMode(pinDuree, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  static bool etatBoutonPrecedent = false;
  byte duree = map(analogRead(pinPotDuree), minPotDuree, maxPotDuree, 0, 15);
  analogWrite(pinDuree,duree);
  Serial.print("durée: ");
  Serial.print(duree );
  Serial.println(" minutes");
  
  bool etatBoutonCommande = !digitalRead(boutonCommande); // on travaille en logique positive
  byte memorisation = duree * 60000;
  if (etatBoutonCommande != etatBoutonPrecedent)
  {
    chrono = millis();
    while(millis() - chrono <= memorisation){
      if (etatBoutonCommande)
      {
        // on a appuyé sur le bouton
        if (drapeau==false)
        {
          // on lance le moteur
          VitesseMCC = 0;
          for (int i = 1; i < 255; i++) {
          VitesseMCC ++;
          analogWrite(pinDuree, VitesseMCC);
          delay(20);
          }
        drapeau = true; // le moteur est en marche
        }
        else
        {
        // on arrete le moteur
        analogWrite(pinDuree, 0);
        drapeau = false;
        } 
      }
    }
    etatBoutonPrecedent = etatBoutonCommande;
    delay(20);  // pour anti rebond
  }
}

Le souci est que lorsque l'on appuie sur le bouton poussoir, le moteur tourne un bref instant puis s'arrête. Comment puis-je corriger le programme de sorte que le moteur tourne pendant le décompte initialisé avec le potentiomètre ?

Cordialement

Bonjour,

une petite erreur ici.. dépassement de la capacité de la variable. byte c'est de 0 à 254.

Encore une autre erreur sur cette ligne. Par défaut les constantes sont de type int. 60000 dépasse la capacité d'un int il faut donc préciser que la constante est de type long en ajoutant un suffixe 60000L


Ici aussi une erreur

millis() retourne un unsigned long et ensuite on fait

donc chrono devrait être de type unsigned long.


En donnant un type correct à memorisation par exemple.

C’est une bonne pratique en effet mais Ce n’est pas tout à fait cela

Les constantes ont le type nécessaire à leur représentation (60000 vaut donc bien 60000) mais les calculs sont effectués par défaut en int s’il y a des constantes littérales petites qui vont tenir sur un int.

Par exemple ceci est une erreur si un int sur la plateforme cible est sur 2 octets

unsigned long uneHeure = 60 * 60 * 1000; // erreur sur MCU 8 bits

les arguments (dans l’ordre d’évaluation) peuvent changer cela cependant donc si on promeut le premier élément en unsigned long le reste du calcul se fait en unsigned long

unsigned long uneHeure = 60ul * 60 * 1000; // OK sur MCU 8 bits Mais pas propre

Mais le mieux reste d’aider le compilo et clarifier les intentions en précisant le type de chacune des constantes

unsigned long uneHeure = 60ul * 60ul * 1000ul; // propre 

Pour le cas précédent, Si durée était un unsigned long alors le calcul serait donc fait en unsigned long même si 60000 n’a pas son ul à la fin (mais vaut mieux le mettre).

Le moteur semble alimenté par votre Arduino ce n’est pas une bonne idée généralement

Bonjour,
Le code précédent est une modification d'un programme opérationnel que j'avais obtenu sur le forum qui lance un moteur à courant continu progressivement lorsque l'on appuie sur le bouton poussoir et l'arrête lorsqu'on le clique une deuxième fois, et auquel j'aimerai ajouter une gestion du temps:

const byte boutonCommande = 3;
int VitesseMCC = 0;
const byte pinMoteur = 6;
bool drapeau = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(boutonCommande, INPUT_PULLUP);
  pinMode(pinMoteur, OUTPUT);
}

void loop() {
  static bool etatBoutonPrecedent = false;
  bool etatBoutonCommande = !digitalRead(boutonCommande); // on travaille en logique positive
  if (etatBoutonCommande != etatBoutonPrecedent)
  {
    if (etatBoutonCommande)
    {
      // on a appuyé sur le bouton
      if (drapeau==false)
      {
        // on lance le moteur
        VitesseMCC = 0;
        for (int i = 1; i < 255; i++) {
          VitesseMCC ++;
          analogWrite(pinMoteur, VitesseMCC);
          delay(20);
        }
        drapeau = true; // le moteur est en marche
      }
      else
      {
        // on arrete le moteur
        analogWrite(pinMoteur, 0);
        drapeau = false;
      }
    }
    etatBoutonPrecedent = etatBoutonCommande;
    delay(20);  // pour anti rebond
  }
}

En prenant toutes les remarques en compte, j'ai changé le programme comme ceci ?

const byte pinPotDuree = A0;
const int minPotDuree = 0;
const int maxPotDuree = 1023;
const byte boutonCommande = 3;
int VitesseMCC = 0;
unsigned long chrono;
const byte pinDuree = 6;
bool drapeau = false;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(boutonCommande, INPUT_PULLUP);
  pinMode(pinDuree, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  static bool etatBoutonPrecedent = false;
  int duree = map(analogRead(pinPotDuree), minPotDuree, maxPotDuree, 0, 15);
  analogWrite(pinDuree,duree);
  Serial.print("durée: ");
  Serial.print(duree );
  Serial.println(" minutes");
  
  bool etatBoutonCommande = !digitalRead(boutonCommande); // on travaille en logique positive
  int memorisation = duree * 60000ul;
  if (etatBoutonCommande != etatBoutonPrecedent)
  {
    chrono = millis();
    while(millis() - chrono <= memorisation){
      if (etatBoutonCommande)
      {
        // on a appuyé sur le bouton
        if (drapeau==false)
        {
          // on lance le moteur
          VitesseMCC = 0;
          for (int i = 1; i < 255; i++) {
          VitesseMCC ++;
          analogWrite(pinDuree, VitesseMCC);
          delay(20);
          }
        drapeau = true; // le moteur est en marche
        }
        else
        {
        // on arrete le moteur
        analogWrite(pinDuree, 0);
        drapeau = false;
        } 
      }
    }
    etatBoutonPrecedent = etatBoutonCommande;
    delay(20);  // pour anti rebond
  }
}

les soucis sont que le moteur s'arrête par intermittence à l'infini lorsque l'on appuie sur le bouton poussoir une première fois, et qu'il refuse de s'arrêter lorsque l'on appuie dessus une deuxième fois.
Quelqu'un aurait-il une idée de ce qui coince dans le programme et/ou dans le programme ?

@J-M-L Serait il plus adapté de câbler avec une alimentation extérieure comme ceci ?:

Cordialement

Oui il faut une alim extérieure mais lire cela

Bonsoir
Merci pour l'information. J'ai oublié de préciser que j'utilise autre chose à la place de la pile qui est représentée, toutefois je crois qu'il est bon de connaître les infos envoyées

J'utilise un chargeur de portable dont j'ai séparé les deux fils à l'intérieur du câble que j'ai branché comme sur le schéma. Toutefois ce branchement n'a pas marché.
Comment dois je changer mon branchement pour que le moteur réponde ?
Comment puis je ajouter un décompte avec le potentiomètre dans le programme post#6 ?

Cordialement

avez vous vérifié que vous avez bien vos 5V en sortie ?
il faut que le GND de l'alimentation du moteur soit connecté au GND de l'arduino (ça a l'air d'être le cas sur votre Fritzing mais qu'en est-il dans la vraie vie ?)

QUe représente la variable duree? Si j'en crois la ligne

C'est un nombre entre 0 et 15, qui est d'ailleurs affiché ensuite en minutes. Mais alors que vient faire le

Puis

L'exprimerait en ms pour l'utiliser avec millis(), mais c'est un int et pas un unsigned long. La temporisation n'aura pas le bonne valeur; elle ne peut pas contenir des nombres supérieurs à 32767.

Bonjour
@J-M-L J'ai revérifier plusieurs fois en inversant les câbles mais toujours rien. Ce n'est seulement que lorsque je remet le câble d'alimentation sur le bord de 5V de la breadbord que le moteur se met en marche. Il ne s'agit pas de fritzing mais de tinkercad. C'est un logiciel en ligne pratique pour faire des simulations basique avec un nombre limiter de composants
image
#4 ARDUINO Simulation sans matériel (Tinkercad 100% gratuit) - YouTube
@vileroi "duree" représente le nombre de minute entre 0 et 15 que l'on veut pré-régler avec le potentiomètre. Le "analogWrite(pinDuree,duree);" sert à visualiser dans le moniteur série le nombre de minute à pré-régler.
Sachant que unsigned long ne peut pas contenir des nombres supérieurs à 32 767 dois-je utiliser une boucle for pour relancer plusieurs fois un compte à rebours plus réduit ?

Cordialement

Non c'est unsigned int qui est limité à 0 et 65535

unsigned long c'est ici

Bah, c'est-à-dire que la première inversion pourrait parfaitement tout flinguer.
On ne vérifie pas le fonctionnement en inversant les câbles. On vérifie le câblage et on s'assure qu'il correspond bien au schéma et ensuite seulement on branche.

oui mais comme on ne vois pas le montage on ne peut pas trop comprendre ce qui se passe.

Autant pour moi pour la confusion de variable et le manque de clarté. Lorsque montage est comme sur l'image ci dessous avec le fil désigné le moteur ne répond pas:

Alors que lorsque le montage est comme sur l'image ci dessous avec le fil désigné le moteur répond à nouveau:

Cordialement

Quel est la référence du mosFET?

Bonsoir,
Il s'agit d'un IRF540N.
image

Cordialement

avez vous vraiment cette breadboard ou vous en avez une longue et le branchement n'est pas exactement là où on le voit ? certaines breadboards longues ont les rails d'alim coupés au milieu et il faut mettre des jumpers si on veut la continuité

d'autre part ce n'est pas une super idée de faire passer un courant fort dans la breadboard, elle n'est pas fait pour cela

@J-M-L Merci

voici mon nouveau programme:

const byte pinPotDuree = A0;
const int minPotDuree = 0;
const int maxPotDuree = 1023;
const byte boutonCommande = 3;
int VitesseMCC = 0;
unsigned long chrono;
const byte pinDuree = 6;
bool drapeau = false;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(boutonCommande, INPUT_PULLUP);
  pinMode(pinDuree, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  static bool etatBoutonPrecedent = false;
  int duree = map(analogRead(pinPotDuree), minPotDuree, maxPotDuree, 0, 15);
  analogWrite(pinDuree,duree);
  Serial.print("durée: ");
  Serial.print(duree );
  Serial.println(" minutes");
  
  bool etatBoutonCommande = !digitalRead(boutonCommande); // on travaille en logique positive
  
  
    if (etatBoutonCommande != etatBoutonPrecedent)
    {
      unsigned long memorisation = duree * 60000;
      if(millis() - chrono >= memorisation){
        analogWrite(pinDuree, 0);
        drapeau = false;
      }
        if (etatBoutonCommande)
        {
          // on a appuyé sur le bouton
          if (drapeau==false)
          {
            // on lance le moteur
            VitesseMCC = 0;
            for (int i = 1; i < 255; i++) {
            VitesseMCC ++;
            analogWrite(pinDuree, VitesseMCC);
            delay(20);
          }
          drapeau = true; // le moteur est en marche
        }
        else
        {
          // on arrete le moteur
          analogWrite(pinDuree, 0);
          drapeau = false;
        } 
      }
      
      etatBoutonPrecedent = etatBoutonCommande;
      delay(20);  // pour anti rebond
    
  } 
}

Le résultat est un peu mieux car le moteur ne tourne plus par intermittence à l'infini. Le souci, cette fois c'est qu'à chaque fois que l'on appuie sur le bouton, le moteur ne fait que tourner un bref instant quelque soit le réglage dans le moniteur série puis s'arrêter au lieu de tourner le temps demander.

Quelqu'un aurait il une idée de comment corriger ce défaut ?

Cordialement

Corrigez le souci de cohérence des temps. Mettre des unsigned long partout, pas des int et rajoutez ul aux constantes de temps.

C’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

Et pour simplifier votre gestion des boutons, éventuellement utilisez la librairie Button dans easyRun de @bricoleau ou alors la librairie OneButton de Matthias Hertel.