Rail Motorisé Moteur pas à pas + interrupteur de fin de course

Bonjour,

J'ai un projet de rail motorisé type rail pour appareil photo. Le projet est finalisé il ne me reste plus qu'a programmer le moteur pas à pas.
le but est de faire coulisser un plateau sur un rail jusqu’à un interrupteur de fin de course puis d'aller en sans inverse jusqu’à l'autre interrupteur de fin de course de l'autre côté et cela indéfiniment.

Je me suis inspiré de cette vidéo https://youtu.be/4Rm1vJ67MkA?feature=shared

La seul différence est que j'ai une carte UNO et non NANO.
Je suis donc équipé de :
-1 moteur pas à pas 28BYJ-48
-1 carte pilote ULN2003
-1 carte UNO
-2 interrupteurs de contact (switch) ou interrupteur de mon kit pour le test

Dans cette vidéo il fournit le montage du moteur et le programme arduino que j'ai souhaité réutilisé étant novice!
J'ai adapté le câblage sur ma UNO en respectant les mêmes ports (excepté pour un GND qui n'est pas au même endroit).

J'ai fait le montage indiqué dans le lien (voir image ci-dessous) et transféré le programme associé mais ça ne fonctionne pas correctement.
Monatge:

Code:

#include <Stepper.h>
const int stepsPerRevolution = 64;
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

#define potent_pin 0
int speed; 
int direction;
int pinButton = 2;  
int power1 = 3;
int power2 = 4;
int power3 = 5;
int power4 = 6;
int GND = 7;

void setup() {
  pinMode(pinButton, INPUT);
  pinMode(power1, OUTPUT);
  pinMode(power2, OUTPUT);
  pinMode(power3, OUTPUT);
  pinMode(power4, OUTPUT);
  pinMode(GND, OUTPUT);
  digitalWrite(power1, HIGH);
  digitalWrite(power2, HIGH);
  digitalWrite(power3, HIGH);
  digitalWrite(power4, HIGH);
  digitalWrite(GND, LOW);
}

bool flag       = LOW;
bool lastButton = LOW;

bool debounce() {
  bool current = digitalRead(pinButton);
  if (current != lastButton) {                  
    delay(10);                                  
    current = digitalRead(pinButton);           
  }
  return current;
}

void loop() {
  int currentButton = debounce();               
  if (lastButton == LOW && currentButton == HIGH)
  { 
    flag = !flag;                               
  }
  lastButton = currentButton;                 
  if (flag == LOW)
      direction = 1;
  if (flag == HIGH)
      direction = -1;
  
  speed = analogRead(potent_pin);     
  speed = map(speed, 0, 1023, 1, 400);   
  speed = constrain(speed, 1, 400);    
  
  myStepper.setSpeed(speed);
  
  myStepper.step(direction);
}

Dans mon 1er test j’alimentai la carte avec le câble de transfert du programme via le PC.
Ne pouvant connecter les interrupteurs de contact sans soudure et facilement sur la "breadboard",j'ai fait le test avec de simple interrupteur présent dans mon kit.
J'avais beaucoup interférence et le moteur changé de sens plus ou moins à sa guise et aucune action lorsque j'appuyais sur les interrupteurs.
Après quelques lectures je me suis demandé si cela ne venait pas du montage qui contenait qu'une seul résistance pour 3 interrupteurs.
J'ai testé avec un seul interrupteur mais rien ne se passait et toujours autant interférence.

Dans mon 2iéme test je me suis alimenté avec une pile (après avoir lu que çà pouvait générer des interférence).
J'ai refait le montage dans son état initial mais toujours le même problème, rien ne se passe quand j’appuie sur les interrupteurs.
Je constate juste une fluctuation faible de l'intensité du moteur (via les diodes de l'ULN2003) signe qu'il se passe quand même quelque chose..

Mon besoin étant urgent je n'avais pas le temps de rentrer dans la compréhension du codage, même si cela m'intérrésse.
Après 2 semaine de recherche d'un code similaire permettant de le reprendre pour mon projet sans sucés, j'ai fini par essayer de comprendre le code et de voir se qui ne va pas.

J'ai quelques doute sur le montage et sur le code (même si tout fonctionne dans la vidéo):

Montage: ne faudrait-il pas 1 résistance par interrupteur?

Codage:
je ne comprends pas la fonction "bool debounce()".

Complément:
Je souhaiterais supprimer le 3iéme bouton (les interrupteurs de fin de courses me suffisent) et ajouter un interrupteur On/Off.
L'idéal serait que le charriot se centre par rapport au 2 extrémités (entre les 2 interrupteurs de fin de course) lors que j’arrête le système (via un bouton de centrage supplémentaire géré via un nombre de pas définit correspondant au centre peut-être?).
Ce dernier point n'est pas urgent et j'aurais le temps de réfléchir et m'intérrésser par la suite (mais je suis ouvert aux pistes/propositions).

Merci d'avance pour votre aide

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

Hello, Ok sorry I'm new here.
I'll transfert it to the francophone section and translate this one.
Thanks

Bonjour @pauloproject et Bienvenue !

UKHelibob écrit qu'il a déplacé le fil de discussion , il l'a donc donc déjà fait, rien de plus à faire pour que les échanges en français se poursuivent ici

Yes, j'ai vu ensuite.
Merci

J'ai détruis ma réponse car j'avais mal lu le schéma.

Je reprend:

C'est une machine à court-circuit ton truc, je me comprends pas que ça puisse marcher.

Par exemple:

Pour lire la position du potentiométre sur A0, il faut que D6 soit à 5V et D7 à 0V.

Si tu oublie D6 ou D7 tu va mesurer 0V ou 5V, pourquoi pas!

Pour les BP et Switch, ça se complique, c'est un générateur de courts-circuits

Si tu appuie sur 1 Switch et le BP, tu mets leurs sorties en court-circuit, c'est je pense un cas qui peut arriver non (être en fin de course d'un côté, et appuyer sur le BP).

Je ne me suis pas pencher sur le code pour comprendre sa philosophie, j'ai compris celle du câblage, c'est une sorte de multiplexeur.

Pour éviter les éventuel cc que j'ai décris, je mettrais des diode "anti retour" sur chaque branche comme cela

Bonjour,

Je vais regarder pour le potentiomètre mais lui fonctionne.

Pour les Switch et le BP normalement non ils ne devraient pas être enfléché en même temps (même si techniquement c'est possible). si il est proche du switch autant attendre plutôt qu'appuyer sur le BP.

Mais sécuriser le système avec des diodes, ok.

Je laisse la résistance (par rapport au précédent post supprimé?)

Merci

Bonjour pauloproject

On peut se passer de diodes et de résistance en inversant la polarité des contacts et en travaillant en mode PULLUP, ainsi un contact fermé donne un LOW, en initialisant l'entrée:
pinMode(contact, INPUT_PULLUP);
on bénéficie de la résistance interne du port.
C'est ce qui se fait, en général, on évite, ainsi, d'amener un potentiel dans les contacts, seulement un GND

Cordialement
jpbbricole

Bonjour,

J'ai lu quelques forums sur l’utilisation de la résistance interne et je comprends le principe d'inversion de polarité.
Cependant je ne maitrise pas le mode PULLUP, comment le coder dans mon cas?

Merci

Comme indiqué dans mon post précédent pinMode...
Dans ton schéma, le fil bleu doit être À GND et la résistance supprimée.

Façon pittoresque de lire trois boutons, le code est cohérent avec ce circuit mais je pense qu'il n'est pas conçu pour un 28BYJ-48 standard.
Ces moteurs ont normalement 2048 pas par tour. Donc:

C'est faux, vous devriez remplacer 64 par 2048.

Avec ce circuit, il ne devrait y avoir aucune interférence, mais je considère le temps anti-rebond comme un peu court (délai (10) ; dans la fonction debounce()), je définirais un minimum de 100.

Essayez ces deux changements et dites-nous.

un exemple de code "simple"

les boutons des deux côtés du moteur sont les fins de course
le potentiomètre règle la durée entre deux pas ou arrête le mécanisme s'il est tout à gauche

wokwi n'a pas le 28BYJ-48 donc il faut le câbler comme il se doit et pas comme sur le dessin, en passant par la carte pilote ULN2003

si vous lancez la simulation et bougez le potentiomètre le moteur se met à bouger, si vous appuyez sur un des deux fin de course, le sens de déplacement s'inverse

le code
#include <Stepper.h>
#include <Toggle.h>

const int stepsPerRevolution = 200;  // à adapter
Stepper moteur(stepsPerRevolution, 8, 9, 10, 11);

const byte pinFdcDroite = 2;
const byte pinFdcGauche = 12;
bool moteurCCW = true;

const byte potPin = A0;
unsigned long attente, dernierPas;
unsigned long maxAttente = 200;
unsigned long minAttente = 2;

Toggle fdcDroite, fdcGauche;

void setup() {
  Serial.begin(115200);
  fdcDroite.begin(pinFdcDroite);
  fdcGauche.begin(pinFdcGauche);
}

void loop() {
  unsigned long nouvelleAttente = map(analogRead(potPin), 0, 1023, maxAttente, minAttente);
  if (nouvelleAttente != attente) {
    attente = nouvelleAttente;
    Serial.print("∆t = ");  Serial.println(attente);
  }

  if (attente < maxAttente && millis() - dernierPas >= attente) {
    moteur.step(moteurCCW ? 1 : -1);
    dernierPas = millis();
  }
  fdcDroite.poll();
  fdcGauche.poll();
  if (fdcDroite.onPress() || fdcGauche.onPress()) moteurCCW = !moteurCCW;
}

Bonjour,

Je persiste dans ma voie, le montage est pitoresque, il utilise des SORTIES pour faire les alimentations du potar, des switch et du BP et à moins de le revoir, ce montage est risque de court circuit entre sorties ce qui est embétant si 2 sorties sont reliées, que l'une est à 0V et l'autre à +5V

Pour lire l'état de K1 (de mon schéma) par exemple, il faut activer (à +5V) D5 et lire l'état de D2.

Si on change la structure du câblage, il faut en faire autant pour le code.

Effectivement il ne peut y avoir 2 fins de courses en même temps (K1 et K2 appuyés) mais matériellement parlant, il peut y avoir 1 fin de course et le BP activés en même temps...

Oui vous êtes très gentil avec ce mot là…

J'ai recopié l'expression de gonpezzi.

Est ce que le code justifie ce type de montage?

Merci pour vos conseils et explication
Je me doutais après mes tests et recherches que ce montage et code n'était pas optimal! Pittoresque, je n'ai pas l'expérience pour le dire...

Je penses qu'il ait préférable que je repartes sur un montage et code plus simple et correct comme celui de J-M-L.

j'essaye et je vous tiens au courant.

Merci

J'ai testé le code de J-M-L mais j'ai quelques problèmes.
La carte pilote ULN2003 doit-être alimentée, je l'ai donc branché sur une alimentation externe.
j'ai branché comme sur le schéma mais ça ne fonctionne pas. Les diodes de la carte clignote mais le moteur tourne pas. Et quand j’appuie sur un des boutons il se lance dans un sens mais très lentement (enfin il vibre).

Comment adapter le montage pour ajouter le branchement de la carte pilote sur la UNO?

Pour faire fonctionner le code j'ai du télécharger le <Toggle.h>. Y en a t-il plusieurs? ai-je installé le bon?

Merci

il faut installer la bibliothèque Toggle disponible dans le gestionnaire de bibliothèques


on trouve le schéma un peu partout par exemple un tuto ici

Bonjour pauloproject

Ne pas oublier de mettre le GND de cette alimentation avec le GND de l'Arduino.

Dans la simulation Wokwi, un grand classique avec ce genre de montage, le croisement de la paire de fils du milieu:
changer
Stepper moteur(stepsPerRevolution, 8, 9, 10, 11);
en
Stepper moteur(stepsPerRevolution, 8, 10, 9, 11);

Croisement qui est fait dans le tuto proposé par @J-M-L

Cordialement
jpbbricole

Bonjour pauloproject

J'ai fait l'essai "en vrai", il faut bien croiser les fils du milieu, voici le code essayé:

#include <Stepper.h>
#include <Toggle.h>

const int stepsPerRevolution = 2048;  // à adapter
Stepper moteur(stepsPerRevolution, 8, 10, 9, 11);

const byte pinFdcDroite = 2;
const byte pinFdcGauche = 12;
bool moteurCCW = true;

const byte potPin = A0;
unsigned long attente, dernierPas;
unsigned long maxAttente = 50;
unsigned long minAttente = 2;

Toggle fdcDroite, fdcGauche;

void setup() {
	Serial.begin(115200);
	fdcDroite.begin(pinFdcDroite);
	fdcGauche.begin(pinFdcGauche);
}

void loop() {
	unsigned long nouvelleAttente = map(analogRead(potPin), 0, 1023, maxAttente, minAttente);
	if (nouvelleAttente != attente) {
		attente = nouvelleAttente;
		Serial.print("∆t = ");  Serial.println(attente);
	}

	if (attente < maxAttente && millis() - dernierPas >= attente) {
		moteur.step(moteurCCW ? 1 : -1);
		dernierPas = millis();
	}
	fdcDroite.poll();
	fdcGauche.poll();
	if (fdcDroite.onPress() || fdcGauche.onPress()) moteurCCW = !moteurCCW;
}

Pour ça il serait nécessaire de donner le nombre de tours de moteur d'un bout à l'autre du rail.

A+
Cordialement
jpbbricole