Débutant: projet de commandes aléatoires de 2 Moteurs CC (moteurs fous ...)

Bonjours,

1er post pour moi. : :slight_smile:

Débutant en programmation, j'apprends . j'ai potassé des pages de code et des livres depuis deux mois environ mais là, mes neurones commencent à souffrir et a mon grand désespoir, j'ai sérieusement besoin d'aide. :frowning:

Mon projet: avec des imprimantes de récupération, je voudrais faire un jeu pour mon fils.

J'essaie (en vain pour le moment) de faire fonctionner deux moteur CC 5 volt en fonctionnement aléatoire.

1 moteur pour l'axe X:
temps de fonctionnement aléatoire, vitesse aléatoire, sens aléatoire.

1 moteur pour l'axe Y:
temps de fonctionnement aléatoire, vitesse aléatoire, sens aléatoire.

Pour chaque axe, il y aura un détecteur optique de fin de course qui inversera le sens de rotation du moteur.

Chaque fonction du sketch si dessous fonctionne indépendamment, mais le tout réunis, les moteur sont comme fou et je m'en arrache le peu de cheveux qu'il me reste...

Tout fonctionne bien jusque la première inversion de sens et puis ensuite ça dérape et au bout de quelques minutes, les moteurs ne tournent plus ou presque plus du tout. j'ai même un allumage des diodes de contrôle sans aucune rotation.

Je suis pas un as, mais j'ai l'impression que: soit j'ai un conflit avec les différents random que j'utilise, soit mes fonction ou commandes ne sont pas au bon endroit.

Merci de vos conseils

Thierry

/*
 * Programme pour le fonctionnement aléatoires de deux moteurs CC.
 * 
 * Les vitesses, les directions et les temps de fonctionnement de chaque moteurs 
 * est contrôlé par des fonctions indépendantes  et aléatoires.
 * Des fins de course optique inversent le sens de rotation pour chaque moteur.
 * 
 * Matériels :
 * 1 carte ARDUINO UNO
 * 1 Shield MotorShield Deek-Robot
 * 2 Moteurs CC 5v 
 */


// --- Déclaration des constantes

const int MotorH = 3; // Déclaration de la broche PWM Moteur H
const int DirH = 12; // Déclaration de la broche de direction moteur H

const int MotorV = 11; // Déclaration de la broche PWM Moteur V
const int DirV = 13; // Déclaration de la broche de direction moteur V

// --- Déclaration des variables

boolean SensH;
boolean SensV;

unsigned long SpeedH;
unsigned long SpeedV;

unsigned long TempsH;
unsigned long TempsV;

unsigned long RandomHT;
unsigned long RandomHV;
unsigned long RandomVT;
unsigned long RandomVV;

// --- Fin de déclarations

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void setup() {

// --- Déclaration des E/S:

  pinMode(MotorH, OUTPUT);// pin Moteur H en sortie
  pinMode(DirH, OUTPUT);// pin direction Moteur H en sorti
  pinMode(MotorV, OUTPUT);// pin Moteur H en sortie
  pinMode(DirV, OUTPUT);// pin direction Moteur H en sorti


// --- Déclaration random des vitesses H & V

  randomSeed (digitalRead (0)),
             RandomHV =  random(50, 255); // --- (H)
  randomSeed (digitalRead (1)),
             RandomVV =  random(50, 255); // --- (V)

// --- Déclaration random des sens des moteur H & V

  randomSeed (digitalRead (0)),
             RandomHT =  random(1000, 3000); // --- (H)
  randomSeed (digitalRead (1)),
             RandomVT =  random(1000, 3000); // --- (V)
             

// --- Déclaration de vitesse de Liaison série pour affichage sur console

  Serial.begin(9600); // 
}

// --- Fin de Void Setup

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void loop() {

  // --- Appel des fonctions de vitesse des moteurs (SPEEDH) H et (SPEEDV) V
  
  SPEEDH ();
  analogWrite (MotorH, RandomHV);
  SPEEDV ();
  analogWrite (MotorV, RandomVV);
  
  // --- Appel des fonctions de temps des moteurs (TEMPSH) H et (TEMPSV) V
  
  TEMPSH ();
  TEMPSV ();
  
  // ---  Appel des fonctions de sens des moteurs (SENSH) H et (SENSV) V
  
  SENSH ();
  digitalWrite (DirH, SensH);
  SENSV ();
  digitalWrite (DirV, SensV);

  // --- Impression sur moniteur série pour contrôle

  Serial.print ("Vitesse H : ");
  Serial.println (RandomHV);
  
  Serial.print ("Vitesse V : ");
  Serial.println (RandomVV);
  
  Serial.print ("Temps   H : ");
  Serial.println (RandomHT);
  
  Serial.print ("Temps   V : ");
  Serial.println (RandomVT);
  
  Serial.print ("Sens    H : ");
  Serial.println (SensH);
  
  Serial.print ("Sens    V : ");
  Serial.println (SensV);
}

// --- Fin de Void Loop

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// --- Début des fonctions

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


int SPEEDH ()  // --- FONCTION SPEEDH --- Commande de la vitesse du moteur H par nombre aléatoire
{
  unsigned long RandNumberHV = millis ();
  unsigned long LastRandNumberHV;

  RandomHV = random(0, 255);

  if (RandNumberHV - LastRandNumberHV > RandomHV) {
    LastRandNumberHV = RandNumberHV;

    digitalWrite(RandomHV, ! digitalRead(RandomHV));

// --- Retour de la variable pour la vitesse du moteur H

    return (RandomHV); 
  }
}
// --- Fin de la fonction SPEEDH

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int SPEEDV ()  // --- FONCTION SPEEDV --- Commande de la vitesse du moteur V par nombre aléatoire
{
  unsigned long RandNumberVV = millis ();
  unsigned long LastRandNumberVV;

  RandomVV = random(0, 255);

  if (RandNumberVV - LastRandNumberVV > RandomVV) {
    LastRandNumberVV = RandNumberVV;

    digitalWrite(RandomVV, ! digitalRead(RandomVV));

// --- Retour de la variable pour la vitesse du moteur V    

    return (RandomVV);
  }
}
// --- Fin de la fonction SPEEDV

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int TEMPSH ()
{
  unsigned long RandNumberHT = millis ();
  unsigned long LastRandNumberHT;

  RandomHT = random(0, 3000);

  if (RandNumberHT - LastRandNumberHT > 1000) {
    LastRandNumberHT = RandNumberHT;

    digitalWrite(RandomHT, ! digitalRead(RandomHT));

// --- Retour de la variable pour le temps de fonctionnement du moteur H    

    return (RandomHT);

  }
}
// --- Fin de la fonction TEMPSH

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int TEMPSV ()
{
  unsigned long RandNumberVT = millis ();
  unsigned long LastRandNumberVT;

  RandomVT = random(0, 3000);

  if (RandNumberVT - LastRandNumberVT > 1000) {
    LastRandNumberVT = RandNumberVT;

    digitalWrite(RandomVT, ! digitalRead(RandomVT));

// --- Retour de la variable pour le temps de fonctionnement du moteur V

    return (RandomVT);

  }
}
// --- Fin de la fonction TEMPSV

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int SENSH () {

  unsigned long MillisH = millis();
  unsigned long PreviousMillisH;


  if (MillisH - PreviousMillisH > RandomHT) {
    PreviousMillisH = MillisH;

    if (SensH == LOW) {
      SensH = HIGH;
    } else {
      SensH = LOW;
    }
    digitalWrite(SensH, ! digitalRead(SensH));
  }

// --- Retour de la variable pour le sens de fonctionnement du moteur H  
  
  return (SensH);
}
// --- Fin de la fonction SENSH

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int SENSV () {

  unsigned long MillisV = millis();
  unsigned long PreviousMillisV;


  if (MillisV - PreviousMillisV > RandomVT) {
    PreviousMillisV = MillisV;

    if (SensV == LOW) {
      SensV = HIGH;
    } else {
      SensV = LOW;
    }
    digitalWrite(SensV, ! digitalRead(SensV));
  }

// --- Retour de la variable pour le sens de fonctionnement du moteur V  
  
  return (SensV);
}
// --- Fin de la fonction SENSV

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// --- Fin des fonctions

Salut et bienvenue
Merci d'avoir utilisé les balises de code, ce n'est pas le cas de tous les nouveaux !
(pas la peine de poster en PJ une image de la console Série, autant poster le texte qui apparait dedans)

le code partait bien avec de la structure et des commentaires mais vous vous mélangez les pinceaux :slight_smile:

Dans vos fonctions 4 fonctions de génération d'aléa, vous avez un truc du genre

  unsigned long RandNumberHT = millis();
  unsigned long LastRandNumberHT;

le nom de variables n'est pas très bien choisi à mon avis (chrono et ancienChrono seraient sans doute mieux (dans certaines vous avez fait mieux avec PreviousMillisV) si vous voulez effectuer un truc tous les ∆t

Mais outre cet aspect, votre variable LastRandNumberXX n'est pas déclarée [url=https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/static/]static[/url] et donc sa valeur est oubliée entre deux appels consécutifs.
(Comme ce sont des variables locales à vos fonctions, pas besoin de noms différents)

Ensuite c'est le grand bazar pour ce que vous modifiez... Par exemple dans TEMPSV() vous faites

  RandomVT = random(0, 3000);

  if (RandNumberVT - LastRandNumberVT > 1000) {
    LastRandNumberVT = RandNumberVT;

    digitalWrite(RandomVT, ! digitalRead(RandomVT));

    // --- Retour de la variable pour le temps de fonctionnement du moteur V
    return (RandomVT);

  }

donc vous essayez de dire "s'il s'est écoulé plus d'une seconde alors"...
Mais là vous vous mettez à lire ou écrire la pin N° RandomVT... c'est pas un N° de pin... vous venez d'affecter un N° aléatoire entre 0 et 2999 pour ce RandomVT...

il n'y a de toutes façons aucune raison d'appeler digitalWrite() ou analogWrite() puisque vous le faites dans la loop()

  SPEEDH();
  analogWrite (MotorH, RandomHV);
  SPEEDV();
  analogWrite (MotorV, RandomVV);

  // --- Appel des fonctions de temps des moteurs (TEMPSH) H et (TEMPSV) V

  TEMPSH();
  TEMPSV();

  // ---  Appel des fonctions de sens des moteurs (SENSH) H et (SENSV) V

  SENSH();
  digitalWrite (DirH, SensH);
  SENSV();
  digitalWrite (DirV, SensV);

Pour ne pas confondre les N° de pin et ce que vous voulez faire, déclarez vos variable qui contiennent un N° de pin avec le mot pin dedans, par exemple

const byte pinMotorH = 3; // Déclaration de la broche PWM Moteur H
const byte pinDirH = 12; // Déclaration de la broche de direction moteur H

const byte pinMotorV = 11; // Déclaration de la broche PWM Moteur V
const byte pinDirV = 13; // Déclaration de la broche de direction moteur V

et le return ne doit pas être dans le if car sinon vous ne retournez rien quand vous n'entrez pas dans ce if() et votre fonction à promis au compilateur de toujours retourner un int. Comme vous n'utilisez pas les valeurs retournées et travaillez avec des variables globales, autant déclarer les fonctions comme ne retournant rien, et remplacer ce int par void (et enlever les instructions return) --> au lieu de

int SENSH() {...

vous faites

void SENSH() {

enfin Dans le setup(), il faut faire une seule fois randomSeed() et on l'appelle plutôt avec analogRead(A0) pour avoir un nombre un peu aléatoire si rien n'est branché sur A0 (un petit bout de fil qui flotte pour faire antenne aide même à avoir une valeur qui bouge bien). L'appel avec digitalRead() ne vous donnera pas bcp de variance (0 ou 1)

D'un point de vue code, les expressions doivent se terminer par un point virgule pas par une virgule donc on n'écrit pas

  randomSeed (digitalRead (0)),
             RandomHV =  random(50, 255); // --- (H)

mais on écrit

  randomSeed (digitalRead (0));
  RandomHV =  random(50, 255); // --- (H)

et vous verrez que l'indentation se met bien d'ailleurs quand vous appuyez ctrl-T ou cmd-T (sur mac)


donc au final ---> il faut que vous repreniez tout votre code dans les fonctions pour essayer de bien définir ce que vous souhaitez faire

si vous voulez modifier une variable globale toutes les 3 secondes par exemple, vous allez écrire

void maFonction() {

  unsigned long chrono = millis();
  static unsigned long ancienChrono = 0; // static pour s'en souvenir entre 2 appels

  if (chrono - ancienChrono > 3000) { // 3000 = 3 secondes
    ancienChrono = chrono;

    // ici faire quelque chose, par exemple inverser le sens
    if (SensV == LOW) SensV = HIGH;
    else  SensV = LOW;   
  }
}

si vous voulez faire quelque chose avec un ∆t aléatoire entre 1s et 3s par exemple, alors au lieu de mettre 3000 en dur, vous pouvez faire varier cette durée

void maFonction() {

  unsigned long chrono = millis();
  static unsigned long ancienChrono = 0; // static pour s'en souvenir entre 2 appels

  if (chrono - ancienChrono > random(1000,3000)) { // entre 1 et 3 secondes d'attente
    ancienChrono = chrono;

    // ici faire quelque chose, par exemple inverser le sens
    if (SensV == LOW) SensV = HIGH;
    else  SensV = LOW;   
  }
}

Bonjour Thierry & J-M-L,

Juste pour information, la dernière fonction de J-M-L ne donnera probablement pas un temps aléatoire entre 1s et 3s dans le cas d'un appel systématique dans la loop.

À chaque appel, un nouveau Δt est tiré au hasard, mais la distribution fera que la condition sera vraie bien plus souvent avec des valeurs proches de 1000 que celles proches de 3000 qui ne donneront qu'un sursis avant le prochain appel de la fonction.

Le mieux serai de 'tirer' cette valeur lorsque la condition est vraie et garantira une répartition correcte.

Une autre variable pour le Δt déclarée static avec une première affectation dans la fonction simplifiera celle-ci.

Zlika:
Juste pour information, la dernière fonction de J-M-L ne donnera probablement pas un temps aléatoire entre 1s et 3s dans le cas d'un appel systématique dans la loop.

À chaque appel, un nouveau Δt est tiré au hasard, mais la distribution fera que la condition sera vraie bien plus souvent avec des valeurs proches de 1000 que celles proches de 3000 qui ne donneront qu'un sursis avant le prochain appel de la fonction.

bon point, le ∆t change à chaque fois qu'on vient dans la fonction, ce serait mieux effectivement

voilà une fonction qui le fait

void maFonction() {
  static unsigned long deltaT = random(1000,3000);

  unsigned long chrono = millis();
  static unsigned long ancienChrono = 0; // static pour s'en souvenir entre 2 appels

  if (chrono - ancienChrono > deltaT) { // entre 1 et 3 secondes d'attente
    ancienChrono = chrono;
    deltaT = random(1000,3000);
    // ici faire quelque chose, par exemple inverser le sens
    if (SensV == LOW) SensV = HIGH;
    else  SensV = LOW;   
  }
}

Bonsoir à vous,

Merci de vos réponses, c'est plus grave que je ne le pensais docteur.

oui, je me mélange les pinceaux, j'ai quelques difficultés avec l’abstrait et j'en suis au moins à la 25 éme version de ce code. ne riez pas pauvre de moi.

A la vue de vos réponses, je vois qu'il me reste du chemin à parcourir et je vois que je suis loin d'avoir tout compris. lol.

Je vais reprendre tout ça a tête reposée en relisant bien pour analyser et bien comprendre.

Je reviendrais d'ici quelques temps pour vous tenir au jus de mes avancées... ou reposer des questions si nécessaire.

Bonne soirée à vous et grand merci encore.

ps: Les temps de millis sont bas, mais juste pour les tests.

N'hésite surtout pas à poser des questions. On est là pour ça :wink: