Aide sur gestion Moteur pas-à-pas avec vis sans fin et écrou à billes

Je souhaite l'afficher en phase de développement pour définir un seuil de coupure. en phase de fonctionnement normal, il n'y aura plus d'affichage.
Pour le switch case, je vais m'y frotter à titre d'entrainement, ça doit être similaire sur le principe au select case du Visual Basic que je maitrise mieux.

@jpbbricole je suis en connections bornier donc je peux faire évoluer mon câblage vers le tien sans problème, ça facilitera effectivement les échanges.
Grand merci une nouvelle fois pour ton aide, je vais tester cette nouvelle version !

Bonjour Jean_la_boissellerie

Ce n'est pas nécessaire, ne change rien puisqu'il suffit de mettre ou pas les remarques les // au début de la ligne, j'ai l'habitude :wink:.
Tu dois juste contrôler, au moment de la "livraison" d'une nouvelle version, que les // soient absents, ainsi:
#define Jean_la_boissellerie // Si paramètres paramètres de Jean

Je suis aussi "issu" du Visual Basic que j'avais et ai toujours du plaisir à pratiquer notamment dans les macro d'Excel.
C'est similaire au vu de la "mécanique", mais en Arduino, c'est très restrictif, ça ne sélectionne que des integer.

Bonne soirée.
jpbbricole

Certes mais il n'est pas nécessaire de faire afficher la position à chaque itération de la boucle qui doit se dérouler quelques milliers de fois par seconde.

Il est aussi possible de passer par un fichier d'en-tête personnel à chacun qui simplifie ce genre de manipulation.

#ifndef Jean_la_boissellerie
  #define Jean_la_boissellerie  // Si paramètres paramètres de Jean
#endif

Merci à Nouveau jpbbricole pour la MàJ, ça fonctionne au top.

@fdufnews , j'ai essayé d'appliquer une temporisation d'une seconde pour lire le courant, mais ça saccade toujours (moins cependant).

void readcurrent()
{
  unsigned long maintenant = millis();

  if (maintenant - datetest>=1000)
    {
    Serial.print(F("I = "));
    Serial.print(sensorCurrent.readCurrentDC());
    Serial.println(F(" A"));
    datetest = maintenant;
    }
}

est-ce mon appel de la fonction readcurrent (après mpap.Run()) qui est mal placé ?
y a t'il un opérateur de concaténation pour ne pas envoyer 3 print ?

Bonjour Jean_la_boissellerie

Super !

Je ne pense pas, par contre la durée de readcurrent(), tu pourrai la chronométrer

Serial.println(millis());
readcurrent();
Serial.println(millis());

pour voir si c'est cette fonction qui fait saccader.

Cordialement
jpbbricole

Si on regarde la librairie, on voit ça:

#define SAMPLE_TIMES        32

float ACS712::readCurrentDC() {
    int sensorValue = 0;
    float sensorCurrent = 0;
    for (int i = 0; i < SAMPLE_TIMES; i++) {
        sensorValue += analogRead(_pin);
    }
    sensorValue = sensorValue >> 5;
    sensorCurrent = (sensorValue - ADC_COUNT_HALF) / ADC_COUNT_ACS712_1A;
    return sensorCurrent;
}

Donc peut-être réduire le nombre d'échantillons. Le bruit de mesure sera un peu plus important.
Attention, le nombre d'échantillons est sensé être une puissance de deux et il faut que le décalage ici sensorValue = sensorValue >> 5; correspondent avec le nombre d'échantillons.
Personnellement, je tenterais

#define SAMPLE_TIMES        8

float ACS712::readCurrentDC() {
    int sensorValue = 0;
    float sensorCurrent = 0;
    for (int i = 0; i < SAMPLE_TIMES; i++) {
        sensorValue += analogRead(_pin);
    }
    sensorValue = sensorValue >> 3;
    sensorCurrent = (sensorValue - ADC_COUNT_HALF) / ADC_COUNT_ACS712_1A;
    return sensorCurrent;
}

Entre nous, faire une librairie pour ça c'est pas vraiment utile. Autant mettre le code directement dans ton programme.

J'ai testé cette méthode en ajoutant une librairie TroykaCurrentS8 modifiée avec sample = 8 et décalage = 3: le moteur se lance et tourne un peu plus longtemps avant de bloquer (environ3s après le démarrage).

Je suis du même avis, surtout que du coup, si c'est intégrer dans une machine à état , il est possible d'avoir le nombre d'échantillon que l'on veut.

@Jean_la_boissellerie si tu as un blocage conséquent et pas juste des saccades, les problèmes est surement ailleurs.

Je ne sais plus si tu nous avais donné le code en entier?

Voici le code entier:

/*
    Name:       AF_boissellerie_MoteurVisAbille.ino
    Created:	28.08.2024
    Author:     BUREAU\admin
	Remarque:	Comande d'un moteur pas à pas et vis à bille pour tiroir.
				https://forum.arduino.cc/t/aide-sur-gestion-moteur-pas-a-pas-avec-vis-sans-fin-et-ecrou-a-bille/1295712/11
	01.09.2024	Première version #15
*/

#include <AccelStepper.h>  // https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html
#include <TroykaCurrentS8.h> // librairie nécessaire au capteur ACS712

//------------------------------------- Moteur pas à pas (mpap)
// Définir les connexions des moteurs pas à pas
const int  mpapDirPin = 2; // Pin qui commande la direction
const int  mpapStepPin = 4; // Pin qui commande les pas
const int  mpapEnablePin = 10; // Pin d'activation du mpap
const long mpapTargetPosition =  57060;  // Définir la position cible (-1500 pas / -37.5mm)

ACS712 sensorCurrent(A2);  // broche de connexion du capteur de courant

unsigned long datetest=0;

float courant=0; // défini une variable courant

AccelStepper mpap(1, mpapStepPin, mpapDirPin);  // Créer une nouvelle instance de la classe AccelStepper

const boolean mpapBitInvertDir = true;  // Pour inverser le bit DIR
const boolean mpapBitInvertStep = true;  // Pour inverser le bit STEP
const boolean mpapBitInvertEna = true;  // Pour inverser le bit ENA

enum {mpapDirToHome, mpapDirToTarget};
int mpapDirTo = mpapDirToTarget;

long mpapStepsPosition = 0;  // En cas d'arrêt en cours, position en poas

//------------------------------------- Endstop vis à bille (vab)
// Définir les pins des capteurs de fin de course
const int vabEndstopHomePin = A0;  // Contact de départ
const int vabEndstopTargetPin = A1; // Contact d^'arrivée
const int vabEndstopEtatOn = LOW; // Etat quand actif

//------------------------------------- Boutons (btn)
// Définir les pins des interrupteurs biposition
const int btnSortiePin = 11; // 6 // Pin de l'interrupteur Sortie
const int btnEntreePin = 3; // 7 // Pin de l'interrupteur Entrée
const int btnEtatOn = LOW; // Etat quand actif

//------------------------------------- Etats du programme
const String prgEtatLabel[] = {"Initial", "en Marche", "en Pause"};
enum {prgEtatInitial, prgEtatEnMarche, prgEtatEnPause};
int prgEtat;  // Etat du programme

void setup()
{
	Serial.begin(115200);
	delay(500);
	Serial.println("\nMoteur pas a pas avec vis a billes");

	mpap.setMaxSpeed(3000); // Définir la vitesse maximale
	mpap.setAcceleration(700); // Définir l'accélération
	
	mpap.setEnablePin(mpapEnablePin);
	//                    DIR                      STEP               ENA
	mpap.setPinsInverted(!mpapBitInvertDir, !mpapBitInvertStep, mpapBitInvertEna);
	
	pinMode(vabEndstopHomePin, INPUT_PULLUP);
	pinMode(vabEndstopTargetPin, INPUT_PULLUP);
	
	pinMode(btnSortiePin, INPUT_PULLUP);
	pinMode(btnEntreePin, INPUT_PULLUP);
	
	mpap.disableOutputs();

	//toolMonitor(); // Pour afficher l'état des ports E/S

	prgEtatChange(prgEtatEnPause);
	mpapDirTo = mpapDirToTarget;
	mpapToEndstopHome();
}

void loop()
{
	if (prgEtat == prgEtatEnPause)
	{
		if (digitalRead(btnSortiePin) == btnEtatOn) // Si le bouton sortie est pressé
		{
			if (digitalRead(vabEndstopTargetPin) == !vabEndstopEtatOn)  // Si pas sur contact arrivée
			{
				Serial.println(F("Bouton SORTIE"));
				prgEtatChange(prgEtatEnMarche);

				mpapDirTo = mpapDirToTarget;
				mpap.move(mpapTargetPosition - mpapStepsPosition);
			}
		} 
		else if (digitalRead(btnEntreePin) == btnEtatOn) // Si le bouton entrée est pressé
		{
			if (digitalRead(vabEndstopHomePin) == !vabEndstopEtatOn)  // Si pas sur contact départ
			{
				Serial.println(F("Bouton ENTREE"));
				prgEtatChange(prgEtatEnMarche);

				mpapDirTo = mpapDirToHome;
				mpap.move(-mpapStepsPosition);
			}
		}
	}


	if ((digitalRead(btnSortiePin) != btnEtatOn && digitalRead(btnEntreePin) != btnEtatOn) && prgEtat == prgEtatEnMarche) // Si le bouton sortie et entrée sont relâchés
	{
		Serial.println(F("Boutons STOP"));
		mpapStop(); // Arrêt du moteur
		prgEtatChange(prgEtatEnPause);
	}

	if (prgEtat == prgEtatEnMarche) // Faire tourner le moteur, si nécessaire
	{
		mpap.run();
    //readcurrent();
	}

	//--------------------------------- Si moteur en fin de course
	if ((digitalRead(vabEndstopHomePin) == vabEndstopEtatOn) && mpapDirTo == mpapDirToHome && prgEtat == prgEtatEnMarche) // Si moteur déjà au départ
	{
		mpapStepsPosition = 0;
		mpapStop();
	}

	if ((digitalRead(vabEndstopTargetPin) == vabEndstopEtatOn) && mpapDirTo == mpapDirToTarget && prgEtat == prgEtatEnMarche) // Si moteur déjà aun target
	{
		mpapStepsPosition = mpapTargetPosition;
		mpapStop();
	}
}

//------------------------------------- Etats du programme
void prgEtatChange(int etatNew)
{
	Serial.println(F("Changement d'etat"));
	Serial.println("\tde " + prgEtatLabel[prgEtat]);

	Serial.println("\ta " + prgEtatLabel[etatNew]);

	prgEtat = etatNew;

	if (prgEtat == prgEtatEnPause)
	{
		mpap.disableOutputs();
	}
	else if (prgEtat == prgEtatEnMarche)
	{
		mpap.enableOutputs();
	}
}

//--------------------------------------lecture courant
void readcurrent()
{
  unsigned long maintenant = millis();

  if (maintenant - datetest>=1000)
    {
    Serial.print(F("I = "));
    Serial.print(sensorCurrent.readCurrentDC());
    Serial.println(F(" A"));
    datetest = maintenant;
    }
}

//------------------------------------ Arrêt du moteur
void mpapStop()
{
	if (mpapDirTo == mpapDirToTarget)
	{
		mpapStepsPosition += mpap.currentPosition();
	} 
	else
	{
		mpapStepsPosition += mpap.currentPosition();
	}
		mpap.setCurrentPosition(0);
		mpap.stop();
}

//------------------------------------ Moteur en position endstopHome
void mpapToEndstopHome()
{
	if (digitalRead(vabEndstopHomePin) != vabEndstopEtatOn)     // Si moteur pas sur contact.
	{
		float savedMaxSpeed = mpap.maxSpeed();  // Pour sauver la vitesse actuelle
		mpap.setMaxSpeed(500);  // Réduire la vitesse

		prgEtatChange(prgEtatEnMarche);
		Serial.println(F("\tMoteur vers endstopHome "));
		mpap.setCurrentPosition(0);     // Moteur position 0
	
		mpap.moveTo(-mpapTargetPosition * 2);

		while (true)
		{
			if (digitalRead(vabEndstopHomePin) == vabEndstopEtatOn)     // Si moteur sur contact.
			{
				mpap.setCurrentPosition(0);     // Moteur position 0
				mpap.stop();
				break;
			}
			mpap.run();
		}
		prgEtatChange(prgEtatEnPause);
		mpap.setMaxSpeed(savedMaxSpeed);  // Restituer la vitesse
	}
	mpapDirTo = mpapDirToTarget;  // Prochaine direction

	mpapStepsPosition = 0;
	Serial.println(F("\tMoteur sur endstopHome "));
}

/*
    Moniteur des E/S
	Attention, reste dans cette boucle.
	Pour arrêter, commenter la ligne:
			//toolMonitor(); // Pour afficher l'état des ports E/S
*/
//------------------------------------- Moniteur des E/S 
void toolMonitor()
{
	while (true)
	{
		Serial.print(F("\nEndstop HOME\t")); Serial.println((digitalRead(vabEndstopHomePin) == vabEndstopEtatOn) ? "ON" : "OFF");
		Serial.print(F("Endstop TARGET\t")); Serial.println((digitalRead(vabEndstopTargetPin) == vabEndstopEtatOn) ? "ON" : "OFF");

		Serial.print(F("Bouton SORTIE\t")); Serial.println((digitalRead(btnEntreePin) == btnEtatOn) ? "ON" : "OFF");
		Serial.print(F("Bouton ENTREE\t")); Serial.println((digitalRead(btnSortiePin) == btnEtatOn) ? "ON" : "OFF");

		Serial.print(F("Moteur ENABLE\t")); Serial.println((digitalRead(mpapEnablePin) == LOW) ? "ON" : "OFF");

		delay(1000);
	}
}

Dans quel état se trouve la machine à états?
Quel message s'affiche lors de l'arrêt?

Bonsoir Jean_la_boissellerie

J'ai fait des essais avec ta bibliothèque TroykaCurrent.h (je n'ai pas trouvé la TroykaCurrentS8.h), ce n'est pas possible elle est très lente.
Par contre avec celle de Rob Tillaart:
image

ça va beaucoup mieux, mais je n'ai pas ton capteur et mon moteur va beaucoup moins vite que le tiens, mais ça vaut la peine d'essayer.

Si tu cherches une bibliothèque quelconque, privilégies cet auteur, il est TOP!

Bonne soirée
jpbbricole

La console affiche ceci sur une sortie:

Bouton SORTIE
Changement d'etat
	de en Pause
	a en Marche
I = 0.03 A
I = 0.40 A
I = 0.29 A
I = 0.71 A
I = 0.21 A
Boutons STOP
Changement d'etat
	de en Marche
	a en Pause

j'arrête moi-même le moteur qui fait un sale bruit !

@jpbbricole, merci pour la source, je vais essayer cette lib ! la S8 est une modif par moi donc pas dispo sur le net :stuck_out_tongue:

Bonjour,

j'ai réalisé un projet assez semblable cette semaine avec un verrou à ouvrir ou fermer et deux interrupteurs. Mon projet est basé sur Rasp Pi Pico.

L'ouverture/fermeture du verrou est commandée par carte magnétique. Selon lequel des interrupteur est fermé, l'action ouvrir ou fermer est choisie et s'exécute jusqu'à ce que l'autre interrupteur soit activé.

Le temps du mouvement, une DEL tri-color indique l'état de la situation: jaune pendant le mouvement, rouge à la fin du mouvement de fermeture, vert à la fin du mouvement d'ouverture.

Le mouvement est assuré par un step-moteur.

Je n'ai pas le temps de lire toute la discussion, toutes les modifications au programme que tu as fait., mais si ça peut t'aider, voici mon code.

#include <Stepper.h>
#include <SPI.h>
#include <MFRC522.h>


//En vue de fonctionner sous Respberry PICO
/*----- Variables, Pins -----*/
//#define STEPS  4      // Number of steps per revolution of Internal shaft
int delai = 60000;      //La DEL restera allumée pendant une minute après la fin du mouvement, affichant alors rouge ou vert alors que durant le mouvement elle affichera jaune
int pas = 25;           // 1 tour = 2048
int sens = 1;
int vitesse = 500;      //Max 500
String libre = "oui";
bool tourne = false;
bool initOUV = false;
bool initFER = false;
int rendu = 0;

int pinSW1 = 26;    //GPIO00 = pin 31  -> Interrupteur fermé lorsque la porte est ouverte  => DEL vert
int pinSW2 = 27;    //GPIO01 = pin 32  -> Interrupteur fermé lorsque la porte est fermée   => DEL rouge
int pinMO1 = 2;     //GPIOO2 = pin 4  -> Mouvement du moteur, contrôleur 1
int pinMO2 = 3;     //GPIOO3 = pin 5  -> Mouvement du moteur, contrôleur 2
int pinMO3 = 4;     //GPIOO4 = pin 6  -> Mouvement du moteur, contrôleur 3
int pinMO4 = 5;     //GPIOO5 = pin 7  -> Mouvement du moteur, contrôleur 4
int pinDER = 13;    //GPIO13 = pin 17 -> Rouge de la DEL;    ... nous n'utiliserons pas le bleu de la DEL tri-colore, car les couleurs souhaitées sont rouge, jaune et vert, néanmoins, le bleu sera connecté à GPIO16 ... au cas où!
int pinDEV = 14;    //GPIO14 = pin 19 -> Vert de la DEL;     ... nous n'utiliserons pas le bleu de la DEL tri-colore, car les couleurs souhaitées sont rouge, jaune et vert, néanmoins, le bleu sera connecté à GPIO16 ... au cas où!
int pinDEB = 15;    //GPIO15 = pin 20 -> Bleu de la DEL;     ... nous n'utiliserons pas le bleu de la DEL tri-colore
byte RST_PIN = 21;  // Configurable, see typical pin layout above
byte SS_1_PIN = 17;   // Configurable, take a unused pin, only HIGH/LOW required, must be different to SS 2

//Création des principaux objets
Stepper moteur(32, pinMO1, pinMO3, pinMO2, pinMO4);
/*
Voici comment connecter le module moteur
PINcarte Defn    PICO    GPIO
A1       GND      ------>>>>>>>>>>   AliM GND
A2       5V        ------>>>>>>>>>>   Alim GND
B1       IN1     4      GPIO2
B2       IN2     5      GPIO3
B3       IN3     6      GPIO4
B4       IN4     7      GPIO5
*/
MFRC522 cartes;   // Create MFRC522 instance.
/*
Voici comment connecter les fils du lecteur de cartes magnétiques
PINcarte Defn    PICO    GPIO
1       3.3V      ------>>>>>>>>>>   Alim 3.3 volts
2       RST       27    GPIO21
3       GND       ------>>>>>>>>>>   Alim GND
4       RQ        ----- >>>>>>>>>>   Libre (non-connecté)
5       MISO      21    GPIO16
6       MOSI      25    GPIO19
7       SCK       24    GPIO18
8       SDA       22    GPIO17
*/

void setup() { 
  Serial.begin(115200);
  Serial.println("");
  delay(550);
  Serial.println("Bonjour les testeurs");
  SPI.begin();        // Init SPI bus
  Serial.println("SPI est démarré.");
  cartes.PCD_Init(SS_1_PIN, RST_PIN); // Init each MFRC522 card
  cartes.PCD_DumpVersionToSerial();

  pinMode(pinSW1, INPUT);   //Interrupteur fermé lorsque la porte est ouverte  => DEL vert
  pinMode(pinSW2, INPUT);   //Interrupteur fermé lorsque la porte est fermée   => DEL rouge
  pinMode(pinMO1, OUTPUT);  //Moteur 1
  pinMode(pinMO2, OUTPUT);  //Moteur 2
  pinMode(pinMO3, OUTPUT);  //Moteur 3
  pinMode(pinMO4, OUTPUT);  //Moteur 4
  pinMode(pinDER, OUTPUT);  //rouge de la DEL
  pinMode(pinDEV, OUTPUT);  //vert de la DEL
  pinMode(pinDEB, OUTPUT);  //bleu de la DEL

  digitalWrite(pinMO1, LOW);
  digitalWrite(pinMO2, LOW);
  digitalWrite(pinMO3, LOW);
  digitalWrite(pinMO4, LOW);
  digitalWrite(pinDER, LOW);
  digitalWrite(pinDEV, LOW);
  digitalWrite(pinDEB, LOW);

  Serial.println("Voici que tout est défini.  Il ne reste qu`à jouer de la porte.");
}  // fin de setup()

void loop() {
  if (++rendu > 100) { rendu = 0; Serial.println("Nous voici en début de boucle."); }
  digitalWrite(pinDER, LOW);
  digitalWrite(pinDEV, LOW);
  digitalWrite(pinDEB, LOW);
  if ( !cartes.PICC_IsNewCardPresent() || !cartes.PICC_ReadCardSerial() ) {
          delay(50);
        return;
  }
  Serial.println("Nous voici en analyse de carte.");
  digitalWrite(pinDER, LOW);
  digitalWrite(pinDEV, LOW);
  digitalWrite(pinDEB, HIGH);
  if (!carteValide(cartes.uid.uidByte, cartes.uid.size)) { return; }
  Serial.println("La carte a été jugée valide.");

  if (libre != "oui") { return; }
  delay(1000);
  Serial.println("Le système est disponible.");
  libre = "ouvrons";
  sens = 1;
  if (digitalRead(pinSW2) == LOW) {
    sens = -1;
    libre = "fermons";
  }
  digitalWrite(pinDER, HIGH);
  digitalWrite(pinDEV, HIGH);
  digitalWrite(pinDEB, LOW);
  while (libre == "ouvrons" || libre == "fermons") {
    Serial.print  ("Libre = ");
    Serial.print  (libre);
    Serial.print  (" avec 1 = ");
    Serial.print  ((digitalRead(pinSW1)==HIGH) ? "HIGH" : "LOW");
    Serial.print  (" et 2 = ");
    Serial.println((digitalRead(pinSW2)==HIGH) ? "HIGH" : "LOW");
    moteur.setSpeed(vitesse); 
    moteur.step(sens * pas);
    if ((digitalRead(pinSW2) == LOW && libre == "ouvrons") || (digitalRead(pinSW1) == LOW && libre == "fermons")) {libre = "oui"; } 
    delay(10);
  }
  

  if (digitalRead(pinSW1) == HIGH) {
    digitalWrite(pinDER, LOW);
    digitalWrite(pinDEV, HIGH);
    digitalWrite(pinDEB, LOW);
    delay(1500);
  }
  if (digitalRead(pinSW2) == HIGH) {
    digitalWrite(pinDER, HIGH);
    digitalWrite(pinDEV, LOW);
    digitalWrite(pinDEB, LOW);
    delay(1500);
  }
  digitalWrite(pinMO1, LOW);
  digitalWrite(pinMO2, LOW);
  digitalWrite(pinMO3, LOW);
  digitalWrite(pinMO4, LOW);
  libre = "oui";
} //Fin de loop()


bool carteValide(byte *buffer, byte bufferSize) {
  String pat = "";
  for (byte i = 0; i < bufferSize; i++) {
    pat = pat + String(buffer[i] < 0x10 ? " 0" : " ");
    pat = pat + String(buffer[i], HEX);
  }
  pat.toUpperCase();
  pat.trim();
  return (pat=="89 A3 F0 97") ?  true : false;
}

Ce code compte quelques traces du développement comme des retour Serial.print qui ne servent à rien d'autre que savoir où on en est ou encore des variables définies qui ne servent plus.

Bonjour à tous,
après plusieurs tentatives de compréhension et d'essai de la librairie de Rob Tillaart, j'abandonne cette fonctionnalité, je perds trop de temps là-dessus et il faut que j'avance sur la suite.

la suite c'est justement le dédoublement du programme car je dois faire fonctionner 2 moteurs pàp + vis.

j'ai dédoublé le programme comme suit, je n'ai pas d'erreur de compilation mais ça ne fonctionne pas. je pense qu'il y a un problème d'ordre et de priorité dans le code mais ça me dépasse.

/*
    Name:       AF_boissellerie_MoteurVisAbille.ino
    Created:	28.08.2024
    Author:     BUREAU\admin
	Remarque:	Comande d'un moteur pas à pas et vis à bille pour tiroir.
				https://forum.arduino.cc/t/aide-sur-gestion-moteur-pas-a-pas-avec-vis-sans-fin-et-ecrou-a-bille/1295712/11
	01.09.2024	Première version #15
*/

#include <AccelStepper.h>  // https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html

//------------------------------------- Moteur pas à pas (mpap)
// Définir les connexions du moteurs pas à pas droit
const int  mpap1DirPin = 2; // Pin qui commande la direction
const int  mpap1StepPin = 4; // Pin qui commande les pas
const int  mpap1EnablePin = 10; // Pin d'activation du mpap
const long mpap1TargetPosition =  57060;  // Définir la position cible (-1500 pas / -37.5mm)

// Définir les connexions du moteurs pas à pas gauche
const int  mpap2DirPin = 5; // Pin qui commande la direction
const int  mpap2StepPin = 6; // Pin qui commande les pas
const int  mpap2EnablePin = 12; // Pin d'activation du mpap
const long mpap2TargetPosition =  57060;  // Définir la position cible (-1500 pas / -37.5mm)

AccelStepper mpap1(1, mpap1StepPin, mpap1DirPin);  // Créer une nouvelle instance de la classe AccelStepper = moteur droit
AccelStepper mpap2(1, mpap2StepPin, mpap2DirPin);  // Créer une nouvelle instance de la classe AccelStepper = moteur gauche

const boolean mpap1BitInvertDir = true;  // Pour inverser le bit DIR
const boolean mpap1BitInvertStep = true;  // Pour inverser le bit STEP
const boolean mpap1BitInvertEna = true;  // Pour inverser le bit ENA

const boolean mpap2BitInvertDir = true;  // Pour inverser le bit DIR
const boolean mpap2BitInvertStep = true;  // Pour inverser le bit STEP
const boolean mpap2BitInvertEna = true;  // Pour inverser le bit ENA

enum {mpap1DirToHome, mpap1DirToTarget};
int mpap1DirTo = mpap1DirToTarget;

enum {mpap2DirToHome, mpap2DirToTarget};
int mpap2DirTo = mpap2DirToTarget;

long mpap1StepsPosition = 0;  // En cas d'arrêt en cours, position en poas moteur droit
long mpap2StepsPosition = 0;  // En cas d'arrêt en cours, position en poas moteur gauche

//------------------------------------- Endstop vis à bille (vab)
// Définir les pins des capteurs de fin de course droits
const int vab1EndstopHomePin = A0;  // Contact de départ
const int vab1EndstopTargetPin = A1; // Contact d^'arrivée
const int vab1EndstopEtatOn = LOW; // Etat quand actif

// Définir les pins des capteurs de fin de course gauches
const int vab2EndstopHomePin = A2;  // Contact de départ
const int vab2EndstopTargetPin = A3; // Contact d^'arrivée
const int vab2EndstopEtatOn = LOW; // Etat quand actif

//------------------------------------- Boutons (btn)
// Définir les pins des interrupteurs biposition droit
const int btn1SortiePin = 11; // 6 // Pin de l'interrupteur Sortie
const int btn1EntreePin = 3; // 7 // Pin de l'interrupteur Entrée
const int btn1EtatOn = LOW; // Etat quand actif

// Définir les pins des interrupteurs biposition gauche
const int btn2SortiePin = 7; // 6 // Pin de l'interrupteur Sortie
const int btn2EntreePin = 8; // 7 // Pin de l'interrupteur Entrée
const int btn2EtatOn = LOW; // Etat quand actif

//------------------------------------- Etats du programme droit
const String prg1EtatLabel[] = {"Initial", "en Marche", "en Pause"};
enum {prg1EtatInitial, prg1EtatEnMarche, prg1EtatEnPause};
int prg1Etat;  // Etat du programme droit

//------------------------------------- Etats du programme gauche
const String prg2EtatLabel[] = {"Initial", "en Marche", "en Pause"};
enum {prg2EtatInitial, prg2EtatEnMarche, prg2EtatEnPause};
int prg2Etat;  // Etat du programme gauche

void setup()
{
	Serial.begin(115200);
	delay(500);
	Serial.println("\nMoteur pas a pas avec vis a billes");

	mpap1.setMaxSpeed(3000); // Définir la vitesse maximale moteur droit 
	mpap1.setAcceleration(700); // Définir l'accélération moteur droit 

  mpap2.setMaxSpeed(3000); // Définir la vitesse maximale moteur gauche
	mpap2.setAcceleration(700); // Définir l'accélération moteur gauche
	
	mpap1.setEnablePin(mpap1EnablePin);
	//                    DIR                      STEP               ENA
	mpap1.setPinsInverted(!mpap1BitInvertDir, !mpap1BitInvertStep, mpap1BitInvertEna);
	
	pinMode(vab1EndstopHomePin, INPUT_PULLUP);
	pinMode(vab1EndstopTargetPin, INPUT_PULLUP);
	
	pinMode(btn1SortiePin, INPUT_PULLUP);
	pinMode(btn1EntreePin, INPUT_PULLUP);
	
	mpap1.disableOutputs();

	mpap2.setEnablePin(mpap2EnablePin);
	//                    DIR                      STEP               ENA
	mpap2.setPinsInverted(!mpap2BitInvertDir, !mpap2BitInvertStep, mpap2BitInvertEna);
	
	pinMode(vab2EndstopHomePin, INPUT_PULLUP);
	pinMode(vab2EndstopTargetPin, INPUT_PULLUP);
	
	pinMode(btn2SortiePin, INPUT_PULLUP);
	pinMode(btn2EntreePin, INPUT_PULLUP);
	
	mpap2.disableOutputs();

	//toolMonitor(); // Pour afficher l'état des ports E/S

	prg1EtatChange(prg1EtatEnPause);
	mpap1DirTo = mpap1DirToTarget;
	mpap1ToEndstopHome();

  prg2EtatChange(prg2EtatEnPause);
	mpap2DirTo = mpap2DirToTarget;
	mpap2ToEndstopHome();
}

void loop()
{
	if (prg1Etat == prg1EtatEnPause)
	{
		if (digitalRead(btn1SortiePin) == btn1EtatOn) // Si le bouton sortie est pressé
		{
			if (digitalRead(vab1EndstopTargetPin) == !vab1EndstopEtatOn)  // Si pas sur contact arrivée
			{
				Serial.println(F("Bouton 1 SORTIE"));
				prg1EtatChange(prg1EtatEnMarche);

				mpap1DirTo = mpap1DirToTarget;
				mpap1.move(mpap1TargetPosition - mpap1StepsPosition);
			}
		} 
		else if (digitalRead(btn1EntreePin) == btn1EtatOn) // Si le bouton entrée est pressé
		{
			if (digitalRead(vab1EndstopHomePin) == !vab1EndstopEtatOn)  // Si pas sur contact départ
			{
				Serial.println(F("Bouton 1 ENTREE"));
				prg1EtatChange(prg1EtatEnMarche);

				mpap1DirTo = mpap1DirToHome;
				mpap1.move(-mpap1StepsPosition);
			}
		}
	}

if (prg2Etat == prg2EtatEnPause)
	{
		if (digitalRead(btn2SortiePin) == btn2EtatOn) // Si le bouton sortie est pressé
		{
			if (digitalRead(vab2EndstopTargetPin) == !vab2EndstopEtatOn)  // Si pas sur contact arrivée
			{
				Serial.println(F("Bouton 2 SORTIE"));
				prg2EtatChange(prg2EtatEnMarche);

				mpap2DirTo = mpap2DirToTarget;
				mpap2.move(mpap2TargetPosition - mpap2StepsPosition);
			}
		} 
		else if (digitalRead(btn2EntreePin) == btn2EtatOn) // Si le bouton entrée est pressé
		{
			if (digitalRead(vab2EndstopHomePin) == !vab2EndstopEtatOn)  // Si pas sur contact départ
			{
				Serial.println(F("Bouton 2 ENTREE"));
				prg2EtatChange(prg2EtatEnMarche);

				mpap2DirTo = mpap2DirToHome;
				mpap2.move(-mpap2StepsPosition);
			}
		}
	}

	if ((digitalRead(btn1SortiePin) != btn1EtatOn && digitalRead(btn1EntreePin) != btn1EtatOn) && prg1Etat == prg1EtatEnMarche) // Si le bouton sortie et entrée sont relâchés
	{
		Serial.println(F("Boutons 1 STOP"));
		mpap1Stop(); // Arrêt du moteur
		prg1EtatChange(prg1EtatEnPause);
	}

	if (prg1Etat == prg1EtatEnMarche) // Faire tourner le moteur, si nécessaire
	{
		mpap1.run();
	}

if ((digitalRead(btn2SortiePin) != btn2EtatOn && digitalRead(btn2EntreePin) != btn2EtatOn) && prg2Etat == prg2EtatEnMarche) // Si le bouton sortie et entrée sont relâchés
	{
		Serial.println(F("Boutons 2 STOP"));
		mpap2Stop(); // Arrêt du moteur
		prg2EtatChange(prg2EtatEnPause);
	}

	if (prg2Etat == prg2EtatEnMarche) // Faire tourner le moteur, si nécessaire
	{
		mpap2.run();
	}

	//--------------------------------- Si moteur droit en fin de course
	if ((digitalRead(vab1EndstopHomePin) == vab1EndstopEtatOn) && mpap1DirTo == mpap1DirToHome && prg1Etat == prg1EtatEnMarche) // Si moteur déjà au départ
	{
		mpap1StepsPosition = 0;
		mpap1Stop();
	}

	if ((digitalRead(vab1EndstopTargetPin) == vab1EndstopEtatOn) && mpap1DirTo == mpap1DirToTarget && prg1Etat == prg1EtatEnMarche) // Si moteur déjà aun target
	{
		mpap1StepsPosition = mpap1TargetPosition;
		mpap1Stop();
	}

  //--------------------------------- Si moteur gauche en fin de course
	if ((digitalRead(vab2EndstopHomePin) == vab2EndstopEtatOn) && mpap2DirTo == mpap2DirToHome && prg2Etat == prg2EtatEnMarche) // Si moteur déjà au départ
	{
		mpap2StepsPosition = 0;
		mpap2Stop();
	}

	if ((digitalRead(vab2EndstopTargetPin) == vab2EndstopEtatOn) && mpap2DirTo == mpap2DirToTarget && prg2Etat == prg2EtatEnMarche) // Si moteur déjà aun target
	{
		mpap2StepsPosition = mpap2TargetPosition;
		mpap2Stop();
	}
  
}

//------------------------------------- Etats du programme 1
void prg1EtatChange(int etatNew)
{
	Serial.println(F("Changement d'etat côté droit"));
	Serial.println("\tde " + prg1EtatLabel[prg1Etat]);

	Serial.println("\ta " + prg1EtatLabel[etatNew]);

	prg1Etat = etatNew;

	if (prg1Etat == prg1EtatEnPause)
	{
		mpap1.disableOutputs();
	}
	else if (prg1Etat == prg1EtatEnMarche)
	{
		mpap1.enableOutputs();
	}
}

//------------------------------------- Etats du programme 
void prg2EtatChange(int etatNew)
{
	Serial.println(F("Changement d'etat côté droit"));
	Serial.println("\tde " + prg2EtatLabel[prg2Etat]);

	Serial.println("\ta " + prg2EtatLabel[etatNew]);

	prg2Etat = etatNew;

	if (prg2Etat == prg2EtatEnPause)
	{
		mpap2.disableOutputs();
	}
	else if (prg2Etat == prg1EtatEnMarche)
	{
		mpap2.enableOutputs();
	}
}


//------------------------------------ Arrêt du moteur droit
void mpap1Stop()
{
	if (mpap1DirTo == mpap1DirToTarget)
	{
		mpap1StepsPosition += mpap1.currentPosition();
	} 
	else
	{
		mpap1StepsPosition += mpap1.currentPosition();
	}
		mpap1.setCurrentPosition(0);
		mpap1.stop();
}

//------------------------------------ Arrêt du moteur gauche
void mpap2Stop()
{
	if (mpap2DirTo == mpap2DirToTarget)
	{
		mpap2StepsPosition += mpap2.currentPosition();
	} 
	else
	{
		mpap2StepsPosition += mpap2.currentPosition();
	}
		mpap2.setCurrentPosition(0);
		mpap2.stop();
}

//------------------------------------ Moteur en position endstopHome moteur droit
void mpap1ToEndstopHome()
{
	if (digitalRead(vab1EndstopHomePin) != vab1EndstopEtatOn)     // Si moteur pas sur contact.
	{
		float savedMaxSpeed1 = mpap1.maxSpeed();  // Pour sauver la vitesse actuelle
		mpap1.setMaxSpeed(500);  // Réduire la vitesse

		prg1EtatChange(prg1EtatEnMarche);
		Serial.println(F("\tMoteur droit vers endstopHome "));
		mpap1.setCurrentPosition(0);     // Moteur position 0
	
		mpap1.moveTo(-mpap1TargetPosition * 2);

		while (true)
		{
			if (digitalRead(vab1EndstopHomePin) == vab1EndstopEtatOn)     // Si moteur sur contact.
			{
				mpap1.setCurrentPosition(0);     // Moteur position 0
				mpap1.stop();
				break;
			}
			mpap1.run();
		}
		prg1EtatChange(prg1EtatEnPause);
		mpap1.setMaxSpeed(savedMaxSpeed1);  // Restituer la vitesse
	}
	mpap1DirTo = mpap1DirToTarget;  // Prochaine direction

	mpap1StepsPosition = 0;
	Serial.println(F("\tMoteur droit sur endstopHome "));
}

//------------------------------------ Moteur en position endstopHome moteur gauche
void mpap2ToEndstopHome()
{
	if (digitalRead(vab2EndstopHomePin) != vab2EndstopEtatOn)     // Si moteur pas sur contact.
	{
		float savedMaxSpeed2 = mpap2.maxSpeed();  // Pour sauver la vitesse actuelle
		mpap2.setMaxSpeed(500);  // Réduire la vitesse

		prg2EtatChange(prg2EtatEnMarche);
		Serial.println(F("\tMoteur gauche vers endstopHome "));
		mpap2.setCurrentPosition(0);     // Moteur position 0
	
		mpap2.moveTo(-mpap2TargetPosition * 2);

		while (true)
		{
			if (digitalRead(vab2EndstopHomePin) == vab2EndstopEtatOn)     // Si moteur sur contact.
			{
				mpap2.setCurrentPosition(0);     // Moteur position 0
				mpap2.stop();
				break;
			}
			mpap2.run();
		}
		prg2EtatChange(prg2EtatEnPause);
		mpap2.setMaxSpeed(savedMaxSpeed2);  // Restituer la vitesse
	}
	mpap2DirTo = mpap2DirToTarget;  // Prochaine direction

	mpap2StepsPosition = 0;
	Serial.println(F("\tMoteur gauche sur endstopHome "));
}

/*
    Moniteur des E/S
	Attention, reste dans cette boucle.
	Pour arrêter, commenter la ligne:
			//toolMonitor(); // Pour afficher l'état des ports E/S
*/
//------------------------------------- Moniteur des E/S 
void toolMonitor()
{
	while (true)
	{
		Serial.print(F("\nEndstop HOME\t")); Serial.println((digitalRead(vab1EndstopHomePin) == vab1EndstopEtatOn) ? "ON" : "OFF");
		Serial.print(F("Endstop TARGET\t")); Serial.println((digitalRead(vab1EndstopTargetPin) == vab1EndstopEtatOn) ? "ON" : "OFF");

		Serial.print(F("Bouton SORTIE\t")); Serial.println((digitalRead(btn1EntreePin) == btn1EtatOn) ? "ON" : "OFF");
		Serial.print(F("Bouton ENTREE\t")); Serial.println((digitalRead(btn1SortiePin) == btn1EtatOn) ? "ON" : "OFF");

		Serial.print(F("Moteur ENABLE\t")); Serial.println((digitalRead(mpap1EnablePin) == LOW) ? "ON" : "OFF");

		delay(1000);
	}
}

je pourrais aussi utiliser 2 Nano mais si ça passe sur 1, ce serait dommage ...

je vous joins un aperçu du dressing en question, je pensais l'avoir présenté déjà mais non:

Bonsoir Jean_la_boissellerie

Il faudrait mettre le programme au complet.

Bonne soirée
jpbbricole

oups, désolé, j'ai fait un copié/merdé ...
c'est réparé :slight_smile:

C'est dommage que tu ne détailles pas ce que tu appel ne pas fonctionner :frowning:
Car en lecture rapide de ton code pas forcément digeste à cause de toutes les variables et "IF"(ce qui n'est pas un reproche :slight_smile: ) et en supposant que les enchainements des ordres (appuis sur tes différents boutons et remonté de tes capteurs de fin de course), ne produise pas ce que tu attends.
Je ne vois pas de boucle d'attente active, qui pourrait gêner l'exécution ou de variable partager entre les deux mouvements.
J'ai vu aussi que tu avais prévus une sortie sur le moniteur série, peut être que si tu nous donnez cette sortie avec les actions que tu as fait et ce que tu t'attends que cela produise, on pourrait plus facilement t'aider.

Oui, surtout qu'il n'y a pas vraiment de raison que cela ne fonctionne pas.

Tu as tester ton programme combiné, mais avec une seul action à la fois?

désolé pour le message laconique, c'est vrai que je ne vous aide pas à m'aider. Je crois que je suis un peu frustré de ne pas pouvoir avancer suffisamment seul ...

lorsque j'appui sur un bouton, rien ne se passe, ni mouvement ni bruit, et le moteur n'est pas activé (la vis tourne à la main). par contre, le retour à endstophome à l'activation fonctionne bien.

voici le qui s'affiche sur le moniteur série:

�B��{�V�JQ�
^T�YFGT�
Moteur pas a pas avec vis a billes
Changement d'etat côté droit
	de Initial
	a en Pause
	Moteur droit sur endstopHome 
Changement d'etat côté droit
	de Initial
	a en Pause
Changement d'etat côté droit
	de en Pause
	a en Marche
	Moteur gauche vers endstopHome

dans cet exemple, j'ai appuyé sur les boutons sortie puis entrée sans effet ni sur le moteur ni sur la console.
(je mets volontairement les caractères bizarres du début qui apparaissent presque à chaque fois)

pour l'instant, mon proto n'a toujours qu'une vis, je ferai le montage à 2 vis quand le programme fonctionnera correctement sur la première vis.

Je me suis permis de faire un wokwi de ton projet.
le programme me semble fonctionner "correctement".
Peux tu nous dire si tu as fait les mêmes branchements ?

Edit, j'ai mis correctement entre guillemet, car il faut rester appuyer sur le bouton de sortie pour que le moteur fonctionne, j'ai un doute que ce soit ce que tu nous avez dit :slight_smile: