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

Bonjour terwal

Oui et non, mais plutôt non, vu que ces variables s'adressent à cette fonction:
setPinsInverted
d'où l'usage de invert dans le nom des variables, c'est pour rester dans le thème.

alors je n'ai pas compris, il ne faut donc pas inverser, c'est le sens normal que tu veux ?
mpapBitInvertDir ou mpapBitInvertStep indique que tu veux inverser, donc si on suit ta logique, tu ne devrais pas faire de !mpapBitInvertStep ou !mpapBitInvertDir
Mais uniquement switcher ta variable entre true et false.

Bonjour à tous,
j'ai testé le programme et il marche parfaitement tant qu'on n'arrête pas le mouvement en milieu de course. quand je l'arrête en milieu de course, j'ai l'impression qu'il perd sa position car il ne s'arrête plus avec la rampe mais avec le fin de course.

autre question, je voudrais que le retour à "Home" lors du branchement se fasse avec une vitesse très inférieure à la vitesse de fonctionnement. j'ai vu sur un tuto qu'une variable déclarée dans une fonction n'était prise en considération que dans la fonction: est-ce que si j'insère une consigne de vitesse comme ceci:

void mpapToEndstopHome()
{
	mpap.setMaxSpeed(1000)
    if (digitalRead(vabEndstopHomePin) != vabEndstopEtatOn)     // Si moteur pas sur contact.
	{
		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);
	}
	mpapDirTo = mpapDirToTarget;  // Prochaine direction

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

ça fonctionnerait ?

Bonjour Jean_la_boissellerie

Je regarde ça dans le courant de l'après-midi.

Cordialement
jpbbricole

Oui tu peux, mais il faut être sûre que redéfinisse la bonne vitesse lorsque tu à fini ou que tu commence une autre action.

Bonjour Jean_la_boissellerie

Je ne pense pas qu'il perd sa position mais comme il est susceptible de s'arrêter n'importe où, je n'ai réussi à faire qu'un arrêt immédiat.

J'ai modifié mpapToEndstopHome(), tu peux régler la vitesse dans:
mpap.setMaxSpeed(100); // Réduire la vitesse
La vitesse d'exploitation est sauvée:
float savedMaxSpeed = mpap.maxSpeed(); // Pour sauver la vitesse actuelle
et restituée:
mpap.setMaxSpeed(savedMaxSpeed); // Restituer la vitesse

//------------------------------------ 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(100);  // 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

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

Bonne après-midi
jpbbricole

Merci beaucoup pour l'adaptation !

pour l'arrêt, je me suis mal exprimé, je veux dire qu'après un arrêt "stop", qu'on reparte dans la même direction vers "target" ou vers "home, il ne s'arrête pas avec la rampe mais avec le capteur sans avoir réduit sa vitesse.
que l'arrêt "stop" soit immédiat , c'est pas un problème.
je peux faire une vidéo si je ne suis pas assez explicite :wink:

Bonjour Jean_la_boissellerie

Oui quand on relâche un bouton ou l'arrivée sur un endstop a le même effet, c'est un arrêt abrupte.

Bonne soirée
jpbbricole

Pour exemple, voici une vidéo d'un aller sans interruption: on voit bien le ralentissement à la fin:

Et voici un aller avec interruption, on voit bien qu'il n'y a aucun ralentissement à la fin (c'est pareil si on revient à "home" après l'interruption):

Bonjour Jean_la_boissellerie

Oui, c'est clair.
Dans la première vidéo, les arrêts se font par la fonction stop des commutateurs ainsi que du endstop à l'arrivée. Donc le moment d'arrêt est imprévisible.
Dans la 2ème vidéo, l'arrêt se fait, non pas sur le endstop mais sur mpapTargetPosition, d'où la possibilité, pour AccelStepper, de prévoir l'arrêt, donc du ralentissement.
Arrêt avec ralentissement, n'importe où, dans ces condition est, pour moi difficile :woozy_face:

Mais, on peut revoir le programme :wink:

Une toute belle journée à toi!
jpbbricole

La librairie AccelStepper n'a pas de fonction sur le nombre de pas exécuter?
Du coup dans ton programme au redémarrage tu demandes le nombres maximal de tour ?

Oui, bien sûre, c'est son fondement même, c'est le cas de la première vidéo, AccelStepper sait où il doit s'arrêter.
Dans la 2ème vidéo, il s'arrête n'importe où par relâchement du bouton, comment prévoire cette position?

Oui, il y a un nombre de tour "objectif" et je pensais naïvement que lors d'un stop, il saurait à quel endroit il s'est arrêté et donc d'où il repartait donc pouvait gérer les rampes mais c'est peut-être plus compliqué.
ce n'est pas un point bloquant de toute façon.

je suis en train d'intégrer un ACS 712 pour mesurer le courant et interrompre en cas de pic qui signifierait blocage du mouvement.

j'ai ajouté une fonction que j'active dans les boucles juste après l'appel de la fonction mpap.moveto(). Du coup je n'ai la valeur qu'une seule fois avant le démarrage (donc presque rien: 0.05A). comment faire pour avoir une lecture continue durant le mouvement et ainsi pouvoir faire un test avec un seuil à ne pas dépasser ?
je me disais qu'il faudrait l'ajouter dans "run" mais comme c'est dans la bibliothèque, ça doit pas être évident à gérer...

/*
    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 <TroykaCurrent.h>

//------------------------------------- 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

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

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

const long mpapTargetPosition =  57360;  // Définir la position cible (-1200 pas / -30mm)

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;

//------------------------------------- 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);
				mpap.setPinsInverted(!mpapBitInvertDir, !mpapBitInvertStep, mpapBitInvertEna);
				mpapDirTo = mpapDirToTarget;
				mpap.moveTo(mpapTargetPosition);
        readcurrent();
			}
		} 
		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);
				mpap.setPinsInverted(mpapBitInvertDir, !mpapBitInvertStep, mpapBitInvertEna);
				mpapDirTo = mpapDirToHome;
				mpap.moveTo(mpapTargetPosition);
        readcurrent();
			}
		}
	}


	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();
	}

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

	if ((digitalRead(vabEndstopTargetPin) == vabEndstopEtatOn) && mpapDirTo == mpapDirToTarget && prgEtat == prgEtatEnMarche) // Si moteur déjà au target
	{
		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()
{
      // sortie des données du capteur de courant
  Serial.print(F("I = "));
  Serial.print(sensorCurrent.readCurrentDC());
  Serial.println(F(" A"));

  delay(500);
}

//------------------------------------ Arrêt du moteur
void mpapStop()
{
	mpap.stop();
	mpap.setCurrentPosition(0);
}

//------------------------------------ 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(1000);  // 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

	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);
	}
}

Lorsque tu te déplaces, tu passes dans cette partie. Rien ne t'empêche d'ajouter un appel de fonction après run()


Si tu regardes la doc il est dit que lorsqu'on appelle stop() une nouvelle destination est définie à l'emplacement actuel ce qui force l'arrêt immédiat.
Tu pourrais éventuellement lire la position actuelle avant d'envoyer le stop()

C'est dans la première qu'il s'arrête n'importe ou?
C'est là ou si AccelStepper sait ou il en ait ou qu'il peut te le dire, tu peux utiliser ce nombre de pas, pour calculer le nombre de pas à faire avant la buté.
Comme normalement AccelStepper sait ou il en ait, le fait de s'arrêter ne doit pas lui faire perdre sa position

Bonjour Jean_la_boissellerie

J'ai revu les vidéo et ai enfin compris ton (mon) problème :wink:

Je vais reprendre mon programme.

A+
Cordialement
jpbbricole

Merci pour ces infos.
J'ai essayé d'ajouter l'appel après "run, mais ça me refait les saccades que j'avais avant, je pense que ça envoie trop d'infos série

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

ou alors c'est plus subtil que ça

Tu m’étonnes avec des print() et un delay() ce n'est pas surprenant.
Si c'est pour faire de la surveillance du courant, inutile de l'afficher il suffit de traiter localement,
Si c'est pour informer, inutile d'afficher à chaque itération une ou deux fois par seconde serait largement suffisant.


Ta loop() est truffée de if avec éventuellement plusieurs conditions et dans chaque if il y a un test de prgEtat.
Commence déjà par faire un switch(prgEtat) avec un case pour chaque état possible cela limitera les tests dans loop() et devrait améliorer la lisibilité du code.

Bonbjour Jean_la_boissellerie

J'ai revu un peu tout ça, essaies cette version.

Pour rendre le développement plus facile, comme on a pas les mêmes ports, j'ai ajouté la compilation conditionnelle, en fonction de cette ligne:
#define Jean_la_boissellerie // Si paramètres paramètres de Jean
#ifdef Jean_la_boissellerie

Si elle n'est pas commentée, c'est tes paramètres qui sont actifs si non les miens, une fois au point, tu pourra supprimer ça.

Le changement est l'ajout de la variable mpapStepsPosition qui retient la position du moteur. Cette variable est mise à jour, essentiellement dans mpapStop().
Ainsi, les déplacements des moteur se font:
En sortie:
mpap.move(mpapTargetPosition - mpapStepsPosition);
En entrée:
mpap.move(-mpapStepsPosition);

Le programme:

/*
    Name:       AF_boissellerie_MoteurVisAbille.ino
    Created:	28.08.2024
    Author:     jpbbricole/Jean_la_boissellerie
	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
	04.09.2024	Ralentissement moteur dans mpapToEndstopHome() #26
	06.09.2024	Modifié mpapStop() #39
*/

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

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

//------------------------------------- Moteur pas à pas (mpap)
// Définir les connexions des moteurs pas à pas
#ifdef Jean_la_boissellerie
	const int  mpapDirPin = 2; // Pin qui commande la direction
	const int  mpapStepPin = 3; // Pin qui commande les pas
	const int  mpapEnablePin = 10; // Pin d'activation du mpap
	const long mpapTargetPosition = 58360;  // Définir la position cible
#else  // Paramètres jpbbricole
	const int  mpapDirPin = 5; // Pin qui commande la direction
	const int  mpapStepPin = 6; // Pin qui commande les pas
	const int  mpapEnablePin = 7; // Pin d'activation du mpap
	const long mpapTargetPosition = 110;;  // Définir la position cible
#endif

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

#ifdef Jean_la_boissellerie
	//------------------------------------- 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 = 6; // Pin de l'interrupteur Sortie
	const int btnEntreePin = 7; // Pin de l'interrupteur Entrée
	const int btnEtatOn = LOW; // Etat quand actif
#else  // Paramètres jpbbricole
	//------------------------------------- Endstop vis à bille (vab)
	// Définir les pins des capteurs de fin de course
	const int vabEndstopHomePin = 8;  // Contact de départ
	const int vabEndstopTargetPin = 4;  // Contact d^'arrivée
	const int vabEndstopEtatOn = LOW; // Etat quand actif

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

//------------------------------------- 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(1500); // Définir la vitesse maximale
	mpap.setAcceleration(200); // 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();
	}

	//--------------------------------- 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();
	}
}

//------------------------------------ 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(100);  // 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, le programme 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);
	}
}

Une toute belle journée à toi!
jpbbricole

Je crois que c'est essentiellement le code de @jpbbricole, je ne sais pas si @Jean_la_boissellerie est assez à l'aise avec le codage pour pouvoir le factoriser?

Par contre je plussoies ta remarque pour la lisibilité du code.