Interférences avec moteur pas-à-pas

Bonjour,

Je suis en train de réaliser une automatisation de table de raboteuse, et je me trouve confronter à de gros soucis d'interférences.

Explication sommaire : un keypad pour taper les valeurs souhaiter, et valider/annuler, 2 afficheur 7 segments (1 pour afficher la hauteur actuel, 1 pour afficher la valeur taper), un driver, un moteur pas à pas.

Dans la pratique, lorsque je testais mon montage en volant sur mon bureau, j'avais assez peu d'interférences, puis j'ai commencé le montage sur la machine hier (un monstre d'acier), juste le moteur est fixé. et là c'est la fête, c'est comme si j’appuyai sur pleins de touches du keypad.

A la base j’utilisai 2 câbles classique pour envoyer le step et le dir au driver, je l'ai remplacé par un câble Ethernet, où j'ai rejoins tout les câbles non utilisé + blindage, puis relié à la terre (car je pense que le problème vient de là), ça ne résout pas mon problème.

Je ne vous parle pas du switch faisant office de endstop pour le home qui lui est directement considéré comme trigger à cause de ces interférences.

Je vous joins le plan de cablage (il manque le endstop)

je suis un peu câblé différemment, dir et step sont sur pin 2 et 3, home switch sur pin 12, toutes les masses sont relié sur le même gnd de la carte, et mon arduino est alimenté par un transo 12V

également le code:

#include <AccelStepper.h>
#include <Keypad.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <math.h>

// Constantes definies par l'utilisateur et dependantes de la raboteuse
#define HAUTEUR_MIN 5               // Hauteur minimale de la table en millimètres
#define HAUTEUR_MAX 225             // Hauteur maximale de la table en millimètres
#define HAUTEUR_HOME 225            // Hauteur de la table au repos en millimètres
#define NBR_PAS_MOTEUR 200        // Nombre de pas par tour du moteur pas-à-pas
#define MICRO_PAS 4         // Nombre de micro pas utilisés par le driver du moteur 
#define PAS_VIS 2         // Pas de la vis de montée de la raboteuse en millimètres
#define DENTS_POULIE_MANIVELLE 40 // Nombre de dents de la poulie se trouvant sur l'axe de la manivelle
#define DENTS_POULIE_MOTEUR 25    // Nombre de dents de la poulie se trouvant sur l'axe du moteur
#define INVDIR false                // Sens de rotation du moteur pas à pas (pour inverser, remplacer "false" par "true") !!! inverser les valeur dans homing

// Profil de vitesse (à modifier par la suite si l'on souhaite être plus rapide ou plus lent) 
#define ACCELERATION 2            // Accélération en mm/s^2
#define VITESSE_MAX 600         // Vitesse maximale de montée de la table en mm/min (ici 500; c'est le premier nombre qu'il faut changer) 
#define INTERVAL 200                // P�riode entre chaque rafraîchissement de l'écran en ms (ici 5 Hz (1/200 ms))

// Definition des entrées/sorties
#define Lig1Pin 11        // Pins concernant les lignes du clavier
#define Lig2Pin 10
#define Lig3Pin 9
#define Lig4Pin 8

#define Col1Pin 7         // Pins concernant les colonnes du clavier
#define Col2Pin 6
#define Col3Pin 5
#define Col4Pin 4

#define StepPin 3         // Pins concernant le moteur pas à pas 
#define DirPin 2

// Constantes définies par l'utilisateur dans le fichier "config.h". Ne pas modifier ici!
#define HHOME (long)(HAUTEUR_HOME*10)   // Hauteur de la table au repos      
#define HMIN (HAUTEUR_MIN*10)            // Hauteur minimale de la table en 1/10 mm
#define HMAX (HAUTEUR_MAX*10)           // Hauteur maximale de la table en 1/10 mm
#define PASPARMM (long)((NBR_PAS_MOTEUR*MICRO_PAS*DENTS_POULIE_MANIVELLE)/(10*PAS_VIS*DENTS_POULIE_MOTEUR))      // Nombre de pas du moteur pour que la table monte de 1/10 mm
#define ACCEL (ACCELERATION*PASPARMM*10)    // Accélération en mm/s^2 (200 = pas/s^2; d'où la multiplication par PASPARMM)
#define ACCELSTOP (10*ACCEL)                // Décélération en cas d'arrêt d'urgence
#define VITESSE ((VITESSE_MAX/6)*PASPARMM)  // Vitesse maximale de montée de la table en mm/min (ici 500; c'est le premier nombre qu'il faut changer)



//HOMING
#define home_switch 12 // Pin 12 connecté au Home Switch (MicroSwitch)
long initial_homing = -1;  // Utilisé pour Home Stepper au démarrage

// Nombre de lignes et de colonnes du clavier
const byte LIG = 4;       // 4 lignes
const byte COL = 4;       // 4 colonnes

// Tableau contenant la répartition des touches du clavier numérique
char numTouches[LIG][COL] = {     // F = Fonctions
  { 1 , 2 , 3 ,'F'},              // I = Incrément/absolu
  { 4 , 5 , 6 ,'I'},              // S = Start
  { 7 , 8 , 9 ,'S'},              // P = stoP
  {'H', 0 ,'C','P'}               // H = Home
};                                // C = Clear

// Connections correspondantes aux lignes et colonnes du clavier
byte rowPins[LIG] = {Lig1Pin, Lig2Pin, Lig3Pin, Lig4Pin};   
byte colPins[COL] = {Col1Pin, Col2Pin, Col3Pin, Col4Pin};

// Création de deux claviers, un avec les nombres et l'autre avec les fonctions
Keypad numClav = Keypad(makeKeymap(numTouches), rowPins, colPins, LIG, COL);

Adafruit_7segment matrix1 = Adafruit_7segment();
Adafruit_7segment matrix2 = Adafruit_7segment();
#define MATRIX1 1
#define MATRIX2 2


// Définition d'un moteur pas à pas (control par driver avec step/dir), ajout du Enable possible avec setEnablePin()
// Step: une transition bas->haut signifie un pas (changement possible avec setPinsInverted())
// Dir:  niveau logique haut signifie rotation sens horaire
AccelStepper moteur(1, StepPin, DirPin);

long hConsigne = 0;                  // Hauteur entrée par l'utilisateur 
long hActuelle = HHOME;              // Variable contenant en permanence la hauteur actuelle de la table     
static byte kpadState;               // Etat de la touche (PRESSED, HOLD, RELEASED, repectivement appuyée, maintenue ( > 2s dans notre cas), relâchée)
char key;                            // Touche appuyée
long precedentMillis = 0;            // Sauvegarde de la dernière fois que l'écran a été rafraîchit
boolean moteurTourne = false;        // Flag signalant lorsque le moteur tourne
boolean moteurStop = false;          // Flag signalant un arrêt d'urgence

void setup() {
 
  Serial.begin(9600);
   
  // Initialisation des 2 digits
  matrix1.begin(0x70);
  matrix2.begin(0x71);
 
  pinMode(home_switch, INPUT_PULLUP);
  
  // Initialisation du moteur
  moteur.setCurrentPosition(hActuelle * PASPARMM);  // Hauteur actuelle au démarrage (Home)
  moteur.setMaxSpeed(VITESSE);                      // Initialisation de la vitesse maximale et de l'accélération du moteur pas à pas
  moteur.setAcceleration(ACCEL);
  moteur.setMinPulseWidth(100);                     // Impulsions de 100 us
  moteur.setPinsInverted(INVDIR, false, false);     // Inversion possible de dir (step et inable restent à leur valeur par défaut)
  // Initialisation des événements relatifs au clavier
  numClav.addEventListener(keypadEvent_num);        // Ajout d'un événement pour le clavier numérique
  numClav.setHoldTime(2000);                        // Par défaut 1000 ms (touche appuyée), maintenant 2000 ms

  // Affichage des valeurs à l'allumage
  //matrix1.println(moteur.currentPosition() / PASPARMM);
  matrix1.println((float)hActuelle /10, 1);
  matrix1.writeDisplay();
  matrix2.println((float)hConsigne /10, 1);
  matrix2.writeDisplay();
  Serial.print("moteur currentPosition ");
  Serial.println(moteur.currentPosition());
  Serial.print("Position Table ");
  Serial.println((float)hActuelle /10, 1);
  

}

void loop() {
  moteurRun();
}


void moteurRun() {
  unsigned long actuelMillis = millis();        // Temps écoulé depuis l'allumage de la carte Arduino
             
  key = numClav.getKey();            // Lecture de la touche du clavier pressée
    
  if(moteurTourne) {
    if(moteurStop) { //utiliser quand touche stop , passe apres au "else"
      moteur.runToPosition();
      moteurStop = false;
      moteur.setAcceleration(ACCEL);
    //  Serial.println("if motorstop");
    }
    
    hActuelle = round(moteur.currentPosition() / PASPARMM);      // Position actuelle du moteur (donc de la table)

    //utiliser quand moteur tourne, passe apres au "else"
    if(moteur.distanceToGo() != 0) {
      moteur.run();
 //     Serial.println("if moteur.distanceToGo");
    }
    else {
      moteurTourne = false;
      hConsigne = 0;
      matrix1.println((float)hActuelle /10, 1);
      matrix1.writeDisplay();
      Serial.print("Hauteur Table ");
      Serial.println((float)hActuelle /10, 1);
      Serial.print("moteur currentPosition ");
      Serial.println(moteur.currentPosition());
      matrix2.println((float)hConsigne /10, 1);
      matrix2.writeDisplay();   
  //    Serial.println("else moteur tourne");
    }
    
     // Rafraîchissement de l'écran seulement si le moteur tourne (autrement pas de variation de la hauteur actuelle!)
     if(actuelMillis - precedentMillis > INTERVAL) {
       precedentMillis = actuelMillis;            // Sauvegarde du temps du dernier rafraîchissement de l'écran
       // matrix1.print((float)hActuelle /10, 1);            // Affichage de la hauteur actuelle en temps reel
        //matrix1.writeDisplay();
     } 
  }
}


// Evénement concernant le clavier numérique
void keypadEvent_num(KeypadEvent key){
    kpadState = numClav.getState();
    swOnState(key);
} 

void swOnState(char key) {
    switch(kpadState) {
      case PRESSED: {
        if(key == 'C') {   // "Clear"
          Serial.println("Clear");
          hConsigne = 0;  
        }
        else if((key >= 0) && (key <= 9)) {       // Chiffre
            hConsigne = (hConsigne * 10) + key;
            Serial.println(hConsigne); 
        }
        else if(key == 'S') {    // "Start"
          // Pour éviter de dépasser les limites de la machine, si une des limites est dépassée, la valeur est limitée
          // et il faut confirmer (ou modifier) en réappuyant sur "Start"
          if(hConsigne > HMAX) {
            hConsigne = HMAX; 
          } 
          else if(hConsigne < HMIN) {
            hConsigne = HMIN;
          }
            else {
              // En appuyant sur Start, le moteur se déplace jusqu'à la position voulue
              moteur.moveTo(hConsigne * PASPARMM);  // Position souhaitée
              Serial.println("Start");
              moteurTourne = true;
            }
        }
        else if(key == 'H') {    // "Home"    
    /**           matrix1.clear();
               matrix1.writeDisplay();
               matrix2.clear();
               matrix2.writeDisplay(); 
               delay(1000);   **/  
           Serial.println("HOMING");
               matrix1.println(" HOM");
               matrix1.writeDisplay();
               matrix2.println("ING ");
               matrix2.writeDisplay();

           //   Définir la vitesse maximale et l' accélération de chaque Steppers au démarrage pour le référencement
               moteur.setMaxSpeed(300.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
               moteur.setAcceleration(ACCEL);  // Définir l'accélération de Stepper
               moteur.setPinsInverted(true, false, false);     // Inversion sens anti-horaire
            Serial.println("Inversion vers interrupteur");
            // Démarrer la procédure de référencement du moteur pas à pas au démarrage
            
              Serial.println("Le chariot va à sa position d'origine HOME. . . . . . . . . . . ");
            
              while (digitalRead(home_switch)) {  // Faire avancer le Stepper CCW jusqu'à ce que le commutateur soit activé
                moteur.moveTo(initial_homing * PASPARMM);  // Définit la position vers laquelle se déplacer
                initial_homing--;  // Diminue de 1  pour le  prochain coup si nécessaire
                moteur.run();
                delay(5);
                }
                Serial.println("Check 1");
                
                moteur.setMaxSpeed(100.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
                moteur.setAcceleration(ACCEL);  // Définir l'accélération de Stepper
                initial_homing = 1;
                moteur.setPinsInverted(false, false, false);     // Inversion sens horaire
            Serial.println("eloignement de l'interrupteur");
              while (!digitalRead(home_switch)) { // Faire avancer le Stepper CW jusqu'à ce que le commutateur soit désactivé
                moteur.moveTo(initial_homing * PASPARMM);  
                moteur.run();
                initial_homing++;
                delay(5);
                }
                 Serial.println("Check 2");
  
              
              // Démarrer la seconde prise de position
  
                moteur.setPinsInverted(true, false, false);     // Inversion sens anti-horaire
                moteur.setMaxSpeed(100.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
                moteur.setAcceleration(ACCEL);  // Définir l'accélération de Stepper
                initial_homing = -1;
Serial.println("Inversion vers interrupteur");
              
              while (digitalRead(home_switch)) {  // Faire avancer le Stepper CCW jusqu'à ce que le commutateur soit activé
                moteur.moveTo(initial_homing * PASPARMM);  // Définit la position vers laquelle se déplacer
                initial_homing--;  // Diminue de 1  pour le  prochain coup si nécessaire
                moteur.run();
                delay(5);
                }
                Serial.println("Check 3");
                
                moteur.setMaxSpeed(100.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
                moteur.setAcceleration(ACCEL);  // Définir l'accélération de Stepper
                initial_homing = 1;
                moteur.setPinsInverted(false, false, false);     // Inversion sens horaire
                        Serial.println("eloignement de l'interrupteur");
              while (!digitalRead(home_switch)) { // Faire avancer le Stepper CW jusqu'à ce que le commutateur soit désactivé
                moteur.moveTo(initial_homing * PASPARMM);  
                moteur.run();
                initial_homing++;
                delay(5);
                }
                Serial.println("Check 4");

  
                Serial.println("Homing Completed");
                Serial.println("");
                Serial.print("moteur currentPosition avant reset suite home");
                Serial.println(moteur.currentPosition());
                
                moteur.setMaxSpeed(VITESSE);      // Définir la vitesse maximale du stepper (plus rapide pour les mouvements réguliers)
                moteur.setAcceleration(ACCEL);  // Définir l'accélération de Stepper
  
                hActuelle = HAUTEUR_HOME*10;  //Réinitialisation de la consigne
                moteurTourne = false;
                hConsigne = 0;
                
                Serial.print("Hauteur Table suite home ");
                Serial.println((float)hActuelle /10, 1);
                Serial.print("Consigne suite home ");
                Serial.println((float)hConsigne /10, 1);
                
                moteur.setCurrentPosition(144000);  //Réinitialisation de la hauteur
                
                Serial.print("moteur currentPosition suite home ");
                Serial.println(moteur.currentPosition());
                
                matrix1.println((float)hActuelle /10, 1);
                matrix1.writeDisplay(); 
                matrix2.println((float)hConsigne /10, 1);
                matrix2.writeDisplay(); 
                Serial.println("affichage suite homing");     
                }
        
        
        else if(key == 'P') {    // "Stop"   
            Serial.println("Stop"); 
            stopMoteur();                                        // En appuyant sur Stop, le moteur s'arrête
        }
        break;
      } 
      default: break;
    }

    matrix2.println((float)hConsigne /10, 1);
    matrix2.writeDisplay();
   // Serial.println("clavier ");
}


// Fonction qui stoppe le moteur -> arrêt d'urgence (déclenchée en appuyant sur la touche "stop")
void stopMoteur() {
  if(moteurTourne) {
    moteur.setAcceleration(ACCELSTOP);      // Augmentation de l'accélération pour un freinage rapide
    moteur.stop();                          // Envoie de la position d'arrêt
    moteurStop = true;                      // Pour signaler à la boucle principale l'urgence... 
  } 
}

J'espère avoir été clair, merci pour votre aide !

Bonsoir nerotheprint

Je n'ai pas encore tout détaillé, mais le premier point a reconsidérer, vu l'environnement, est d'abaisser l'impédance de home_switch en lui mettant une résistance de 1k contre +5V, l'impédance fournie par pinMode(home_switch, INPUT_PULLUP); est beaucoup trop haute, elle est de quelques dizaines de kOhms. l'environnement est très perturbé.
Contrôle bien que tout les GND sont bien ensemble et de bonne section.

Cordialement
jpbbricole

Bonsoir jpbbricole,
Merci pour cette première réponse.

Je vais déjà essayer de mettre une résistance comme indiqué, on est d'accord qu'il vaut mieux qu'elle soit au plus proche de la carte (donc sorti pin 12), plutôt que vers le switch ? j'ai un bon mètre de câble.

Concernant les GND, ils sont bien tous relié à la même broche ( les 2 digit 7 segments, le home switch, et le - du dir, step et ena du driver.
J'ai utilisé les brins d'un câble Ethernet pour mes branchements ( à par pour le switch où j'ai pris du câble audio rouge et noir).

Bonsoir nerotheprint

Si en déconnectant complètement le clavier au niveau de l'Arduino, il y a toujours des interférences?'

Cordialement
jpbbricole

Bonjour,

Je test ça dès que possible !

Bonsoir jpbbricole,

Désolé d'avoir tarder à répondre, la machine n'est pas chez moi !

Donc je suis aller testé ça tout à l'heure, il semble effectivement, que c'est le clavier qui prend les interférences ! parfois tout va bien, parfois c'est la fête !

Je ne vois pas trop comment améliorer ça... Ce qui me vient à l'esprit ça serait de mettre un signal haut tout le temps, et de détecter l’appuie lorsqu'il n'y à plus de signal. facile à faire pour un bouton/switch, mais pour une matrice... aucune idée !

Sinon, la petite résistance pour le home switch semble plutôt bien fonctionner ! il faudrait que je tests plus en profondeur.

Merci

Bonsoir nerotheprint

As-tu une référence sur ton clavier?
Tu pourrais câbler ton clavier avec un câble blindé.
Ou autre solution, transformer ton clavier en i2C avec un PCF8574, tu n'aurai plus que 2 fils et l'alimentation, c'est plus facile à protéger. Ca utilise la bibliothèque I2CKeyPad.

Cordialement
jpbbricole

Je n'ai pas de référence pour la matrice, mais elle vient d'ici, (modèle A).

Pour le câble blindé, ça me parait compliqué vu la configuration du clavier, il a un petit 10cm en souple que je ne peux pas blinder...
Actuellement j'ai ça en câble :

Pour le PCF8574, pourquoi pas, ça ne devrait pas gêner les 2 digit qui sont en i2c je pense.
Il faudrait "juste" que j'arrive à adapter mon code avec cette nouvelle bibliothèque.

Reste ces fameux 10cm de souple, je ne sais pas s'ils vont m'embêter.

EDIT: Je regarde la bibliotheque i2ckeypad, c'est moi ou ça ne change quasiment rien au code ? J'ai l'impression qu'il faut juste inclure la bibliotheque, ajouter l'adresse i2c, et l'inclure lors de l'initialisation du keypad. ça me parait trop facile :sweat_smile:

Bonsoir nerotheprint

Un autre solution que je n'ai pas essayé, serait de mettre des résistances de PULL_UP de 4.7k sur les 4 entrées de la matrice, afin d'abaisser l'impédance de ces entrées, comme ceci

Cordialement
jpbbricole

Je viens de tester le montage, sans driver/moteur, donc sans sources d'interférences.

résistances de 4.7k sur les 4 entrée, donc colonnes (pin 4 à 7 pour moi), le clavier fonctionne toujours, il faudrait que j'essaie en condition réel.
Il faut aussi que je trouve un moyen de brancher les résistances au plus proche de la carte, de façon propre et sans risques de déconnections.

Merci pour ces idées

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.