Besoin d'aide pour programmation moteur pas à pas

Bonjour,
je débute en arduino et ceci est mon premier post lié à la programmation (aprés quelque déboire entre mon laptop et une simili leonardo olimex).
Je réalise actuellement une structure pour scanner 3D. Pour cela je dois équipé un plateau d’un moteur pas à pas qui tournera entre chaque prise d’image du scaner mais pour l’instant le programme ne marche pas.
J’essaie de réaliser bout par bout, donc pour l’instant je simule les changements de bobine avec des leds mais y a une couil… dans le potage et je pense que c’est moi :blush:
Alors je sais qu’il y a super simple pour ça avec la librairie mais je ne doit pas l’utiliser.
Donc mon code pour l’instant sert juste à rentrer une valeur via le terminal serie et faire changer de bobine

const int A_1=2 ;                  //bobineA1
const int A_2=3 ;                  //bobineA2
const int B_1=4 ;                  //bobineB1
const int B_2=5 ;                  //bobineB2
int Deplacement = 0;
int Position = 0 ;// la constant position sert a garder en mémoire l’emplacement du moteur
                       // pour repartir au pas suivant

void setup()
{
	pinMode (A_1,OUTPUT) ; // mise en sortie des pins pour le controle des bobines
	pinMode (A_2,OUTPUT) ;
	pinMode (B_1,OUTPUT) ;
	pinMode (B_2,OUTPUT) ;
	Serial.begin(9600);
}

void loop()
	{
		if (Serial.available() != 0)
		{Deplacement = Serial.read();}
                mouvement_pap(Deplacement,Position) ;
		
	}


int mouvement_pap(int x, int Mouvement)
{
	if (x>=0)
		{
		for (int i=1 ; i<= x ; i++)
			{
                        Mouvement = Mouvement+i;
			if( Mouvement>4)
                                 {
                                       Mouvement=Mouvement%4 ;
                                       if (Mouvement==0) {Mouvement=4 } ;}
                                 }  //permet de rester dans  l’intervalle 1 à 4
                         Changement_de_pas(Mouvement) ;
                        }
		}

	else
		{
		for (int i=-1 ; i>=x ; i--)
			{
                                Mouvement =Mouvement+ i ;
				if (Mouvement < -4)
				{
					Mouvement=Mouvement%4 ;
					if (Mouvement==0) {Mouvement=1 ;}
                                 }
                                Changement_de_pas(Mouvement) ;
			}
		}
		return Mouvement ;
	}
int Changement_de_pas(int p)
{
switch(p)
		{
				case 1 :
				digitalWrite(A_2, LOW) ;
				digitalWrite(B_1, LOW) ;
				digitalWrite(B_2, LOW) ;
				digitalWrite(A_1, HIGH) ;
				break;

			        case 2 :
				digitalWrite(A_2, LOW) ;
				digitalWrite(A_1, LOW) ;
				digitalWrite(B_2, LOW) ;
				digitalWrite(B_1, HIGH) ;
				break;

                                case 3 :
				digitalWrite(A_1, LOW) ;
				digitalWrite(B_1, LOW) ;
				digitalWrite(B_2, LOW) ;
				digitalWrite(A_2, HIGH) ;
				break;

                                case 4 :
				digitalWrite(A_1, LOW) ;
				digitalWrite(B_1, LOW) ;
				digitalWrite(B_2, LOW) ;
				digitalWrite(A_2, HIGH) ;
				break;
	
			        default :
				break;
		}

                digitalWrite(A_1, LOW) ; //remise à 0 des bobines
		digitalWrite(B_1, LOW) ;
		digitalWrite(B_2, LOW) ;
		digitalWrite(A_2, LOW) ;
}

j’ai beau retourner tous ça dans ma tête mais je ne vois pas mon erreur ( mais celle de mes parents si :cold_sweat:)
tous petit coup de main est bon à prendre
merci d’avance et bon week-end de paques

Oulala que c'est compliqué ... J'avoue que j'ai du mal à comprendre ta logique :s

A ta place j'aurais fait une fonction FaireUnPas(), qui utiliserait une variable globale pour mémoriser à quelle position il en est. Il suffirait ensuite dans le programme principal de lancer cette fonction dans une boucle dont la limite est le nombre de pas à réaliser.

En plus il faut penser à mettre des delay() entre chaque mouvement, sinon tu ne verras pas grand chose ...

Moi il y a 2 ou 3 trucs qui me choquent

Dans cette partie,

if (Mouvement < -4)
{
Mouvement=Mouvement%4 ;
if (Mouvement==0) {Mouvement=1 ;}
}
Changement_de_pas(Mouvement) ;
}
}
return Mouvement ;
}

x est négatif pourtant dans le test if (Mouvement==0) {Mouvement=1 ;} tu remet Mouvement à 1 ne serais-ce pas plutôt -1
Autre chose tu te compliques la vie en faisant varier ton index de 1 à 4 ce qui t’oblige à ajouter un test >4 (ou <-4) pour repartir de 1 (ou -1)
Il serait plus simple de faire varier l’index de 0 à 3 et de n’utiliser que le modulo.

Dans la fonction Changement_de_pas(int p) tu mets les sorties à 0 juste après le switch case ce qui fait que les sorties n’ont pas le temps de bouger.
D’ailleurs pourquoi cette remise à 0 des sorties???

Pourquoi se compliquer la vie ?
En pas entiers on a quatre sorties avec quatre combinaisons possibles.
En demi pas, il y a huit combinaisons.
Un tableau de byte.
On incrémente-décrémente l'indice .
On recopie sur chaque port la valeur lue.

En full step :
0000 0101
0000 1001
0000 0110
0000 1010

Indice ++ on tourne dans un sens.
Indice -- on tourne dans l'autre sens.

Me revoilà, deja un merci à ceux qui m’ont répondu et c’est vrai que mon code était d’une lourdeur.
Donc voila le nouveau

//test non fini sans reprise de pas
const int A_1=2 ;                  
const int A_2=3 ;                  
const int B_1=4 ;                  
const int B_2=5 ;                  
char bobineA1[]={LOW,HIGH,HIGH,HIGH} ;
char bobineA2[]={HIGH,HIGH,LOW,HIGH} ;
char bobineB1[]={HIGH,LOW,HIGH,HIGH} ;
char bobineB2[]={HIGH,HIGH,HIGH,LOW};
int Deplacement = 0;// nombre de pas demandé


void setup()
{
	pinMode (A_1,OUTPUT) ; // mise en sortie des pins pour le controle des bobines
	pinMode (A_2,OUTPUT) ;
	pinMode (B_1,OUTPUT) ;
	pinMode (B_2,OUTPUT) ;
	Serial.begin(9600);

      
}

void loop()
	{
        if (Serial.available() != 0)
	    {Deplacement = Serial.read();}
	FaireUnPas(Deplacement);
     
	}
int FaireUnPas(int i)
	{
	if (i>0)
			{
			for(int j=0;j<i;j++)
				{
                                int k=0;
                                k=j;
                                if (k>3) {k=k%4;}
                                digitalWrite (A_1,bobineA1[k]);
                                digitalWrite (A_2,bobineA2[k]);
                                digitalWrite (B_1,bobineB1[k]);
                                digitalWrite (B_2,bobineB2[k]);
                                delay(1000);
				}
                        digitalWrite (A_1,HIGH);//remise à zero des bobines apres mouvement
                        digitalWrite (A_2, HIGH);
                        digitalWrite (B_1, HIGH);
                        digitalWrite (B_2, HIGH);
                        delay(1000);

			}
	else
			{
			for(int j=0;j>i;j--)
				{
				int k=0;
				k=j+3;
				if (k<=-1) {k=j%-4;k=k+3;}
                                digitalWrite (A_1,bobineA1[k]);
                                digitalWrite (A_2,bobineA2[k]);
                                digitalWrite (B_1,bobineB1[k]);
                                digitalWrite (B_2,bobineB2[k]);
                                delay(1000);
				}
                        digitalWrite (A_1,HIGH);//remise à zero des bobines apres mouvement
                        digitalWrite (A_2,HIGH);
                        digitalWrite (B_1,HIGH);
                        digitalWrite (B_2,HIGH);
                        delay(1000);

			}
	}

le problème maintenant c’est que quoi que je rentre dans le moniteur (même une lettre) les leds tourne en boucle(je test avec des leds pour rien griller).Et si je rentre une variable négative il tourne dans le même sens.
Je peut me poser en ce moment sur le problème car j’ai un peu de temps pour travailler dessus au taf.
Pour répondre aussi à la question du pourquoi une remise à zéro c’est que j’ai lu sur le net qu’il valait mieux les remettre à zéro aprés le déplacement en attendant une nouvelle demande de rotation.
Merci d’avance pour l’aide

Regarde ici, cela pourra peut être t'aider :

Merci du lien JeF (si ça ne t'ennuie pas que j’abrège ton prénom) :cold_sweat:
Donc voici mes problèmes actuel (toujours un peu les même mais je ne trouve pas les infos et j'ai beau retourner le truc dans tous les sens...)
-la valeur repris dans le serial monitor ne prend pas en compte le signe de celle-ci
-ma boucle for semble tourner en boucle (et moi en eau de boudin)
merci d'avance pour les pistes de solutions :slight_smile:

ça ne me dérange pas....

Ce qui me dérange par contre c'est qu'il n'y a rien dans ton programme pour lire ce que tu envoies sur le port série par le biais du serial monitor.... :grin:

Ah ok on m'aurais mentit (mon cerveau me ment tous le temps ce petit...)
Je croyais que

if (Serial.available() != 0)
	    {
            Deplacement = Serial.read();
	    FaireUnPas(Deplacement);
            Deplacement=0;
}

me permettait de lire ce que j'envoyais par le serial monitor
Merci JeF je me replonge dedans :sweat_smile:

Jean-François:
Ce qui me dérange par contre c'est qu'il n'y a rien dans ton programme pour lire ce que tu envoies sur le port série par le biais du serial monitor.... :grin:

Si il y a ce code

	    {Deplacement = Serial.read();}
	FaireUnPas(Deplacement);

Le problème je crois c'est qu'il y a un amalgame entre le code ascii du caractère reçu et sa valeur.
Ou alors les valeurs envoyées ne le sont pas à partir du serial monitor.

@tazzzbass
Qu'est-ce que tu envoies et qu'est-ce que tu t'attends à recevoir?
J'ai l'impression que tu confonds caractère et valeur

Oui c'est ce que je viens de comprendre en relisant le tuto des zéros
enfaîte je veut rentrer une valeur positive ou négative et ainsi faire tourner mon moteur pap dans un sens ou dans l'autre si je rentre 5 par exemple, faire 5 pas dans un sens (horaire je crois) et si je rentre -5 faire 5 pas en trigo, mais je viens de m’apercevoir que le serial lit le code ASCII :roll_eyes:
Merci Fdu

je viens de m’apercevoir que le serial lit le code ASCII

Petite erreur d’interprétation.
Le Serial lit ce qu’on lui envoi.
Un terminal (le Serial Monitor est un terminal) envoie le code ASCII des caractères que l’on entre au clavier.
Si tu utilises un programme coté PC pour piloter ton arduino rien ne t’empêche d’envoyer des valeurs directement sous forme d’octets signés. Ou bien en utilisant un codage qui t’arrange.
Il faut adapter le programme dans ton Arduino en fonction de ce qu’il y a en face et aussi de ce que tu veux faire. Ne jamais oublier que lorsqu’on développe un application qui utilise un moyen de communication il est toujours bon de connaitre le fonctionnement des 2 extrémités pour ne pas se tromper.

fdufnews:

Jean-François:
Ce qui me dérange par contre c'est qu'il n'y a rien dans ton programme pour lire ce que tu envoies sur le port série par le biais du serial monitor.... :grin:

Si il y a ce code

	    {Deplacement = Serial.read();}
FaireUnPas(Deplacement);

Oupssss.... :grin:

Pas bien de faire trois chose en même temps.... XD

Bon ça avance, j’ai trouvé les 2 fonctions qui me manquaient

Serial.parseInt();//permet de récupérer la chaîne de caractère tapé dans le serial monitor
Serial.flush();// permet de vider le buffer pour ne pas tourner en boucle dans la fonction loop

Ce qui nous donne au final (je le met si un jour quelqu’un cherche a faire le même type de prog sans la librairie

//test non fini sans reprise de pas
const int A_1=2 ;                  
const int A_2=3 ;                  
const int B_1=4 ;                  
const int B_2=5 ;                  
char bobineA1[]={HIGH,LOW, LOW, HIGH} ;
char bobineA2[]={LOW ,HIGH,HIGH,LOW} ;
char bobineB1[]={HIGH,HIGH,LOW, LOW} ;
char bobineB2[]={LOW ,LOW, HIGH,HIGH};
int Deplacement = 0;// nombre de pas demandé


void setup()
{
	pinMode (A_1,OUTPUT) ; // mise en sortie des pins pour le controle des bobines
	pinMode (A_2,OUTPUT) ;
	pinMode (B_1,OUTPUT) ;
	pinMode (B_2,OUTPUT) ;
	Serial.begin(9600);
        

      
}

void loop()
	{
 
        if (Serial.available() != 0)
	    {Deplacement = Serial.parseInt();}
	FaireUnPas(Deplacement);
        Serial.flush();
        
	}
int FaireUnPas(int i)
	{
	if (i>0)
			{
			for(int j=0;j<i;j++)
				{
                                int k=0;
                                k=j;
                                if (k>3) {k=k%4;}
                                digitalWrite (A_1,bobineA1[k]);
                                digitalWrite (A_2,bobineA2[k]);
                                digitalWrite (B_1,bobineB1[k]);
                                digitalWrite (B_2,bobineB2[k]);
                                delay(500);
				}
                        digitalWrite (A_1,LOW);//remise à zero des bobines apres mouvement
                        digitalWrite (A_2, LOW);
                        digitalWrite (B_1, LOW);
                        digitalWrite (B_2, LOW);
                        delay(500);
			}
	else if (i<0)
			{
			for(int j=0;j>i;j--)
				{
				int k=0;
				k=j+3;
				if (k<=-1) {k=j%-4;k=k+3;}
                                digitalWrite (A_1,bobineA1[k]);
                                digitalWrite (A_2,bobineA2[k]);
                                digitalWrite (B_1,bobineB1[k]);
                                digitalWrite (B_2,bobineB2[k]);
                                delay(500);
				}
                        digitalWrite (A_1,LOW);//remise à zero des bobines apres mouvement
                        digitalWrite (A_2,LOW);
                        digitalWrite (B_1,LOW);
                        digitalWrite (B_2,LOW);
                        delay(1000);

			}
	}

Maintenant je boss sur le renvoi de la position du moteur pour qu’il reparte au pas suivant et non toujours sur le premier couple
Merci à ceux qui m’ont aidés et a gogole 8)

tazzzbass:

Serial.flush();// permet de vider le buffer pour ne pas tourner en boucle dans la fonction loop

Attention cette fonction a changé de but au moment du passage en 1.0.x :wink:

Elle ne "vide" pas (enfin plus) le buffer en entrée mais en sortie :

Waits for the transmission of outgoing serial data to complete. (Prior to Arduino 1.0, this instead removed any buffered incoming serial data.)

Effectivement Skywodd sans le serial.flush() le programme marche de même. Si tu as le temps un jour j'aimerais que tu m'explique à quoi sert la fonction alors car là j'avoue être perdu :.
J'ai des soucis aussi avec la fonction return mais je vais ouvrir un autre post.

Serial.flush() permet d'attendre que le buffer d'émission soit vide. En gros que tout à été envoyé :wink:

Serial.print() n'étant pas une fonction bloquante