Problème réactivité moteur pas à pas

Bonjour,

L'objectif est de contrôler la hauteur d'une électrode avec un moteur pas à pas et de vérifier cette hauteur en mesurant la tension en volt.

Le script fonctionne bien, le moteur tourne dans les deux sens et s'arrête entre target1 et target2 (marge d'erreur pour évite le changement de rotation en continu).

Le problème est que le changement de direction de la seconde condition à la première est extrêmement lent (environ 1 secondes) mais quasi instantanée de la première à la deuxième.

Quelle modification pour que le moteur change rapidement de direction dans les deux sens ?

merci.

#include <Stepper.h>

#define Sensorpin A0
#define directionPin 8
#define stepPin 9
#define stepsPerRevolution 800 // Nombre de pas par révolution 

Stepper myStepper(stepsPerRevolution, stepPin, directionPin); 

float TARGET = 5.0;                     // Tension à Maintenir
float target1 = TARGET - 0.5;    // Marge d'erreur 1
float target2 = TARGET + 0.5;   // Marge d'erreur 2


void setup() {
  myStepper.setSpeed(400); // Définir la vitesse du moteur 
  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  
}

void loop() {
  
  // Lecture de la valeur du capteur et conversion en tension
  int value = analogRead(Sensorpin);
  int voltage = map(value, 0, 1024, 0, 2500);
  voltage /= 98; // Conversion correcte de l'échelle de voltage

   if (voltage < target1) { 
   myStepper.step(-stepsPerRevolution);
   
   }
   else if(voltage > target2)
    { myStepper.step(stepsPerRevolution);
   }   
   
 }

: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

Votre code « fonctionne »... Mais votre matériel est-il correctement câblé?

bonjour xfpd,

Tout me semble correctement cablé.
J'utilise un nema 17 avec un dm556.
dm556 reglé sur 800steps et 0.5amp.
PUL- ET DIR- Shunté et mis sur GND.
DIR + sur Pin 8 et PUL+ sur Pin 9.

J'utilise un capteur de tension classique 0-25v

Tout fonctionne, pour les tests j'utilise un alimentation de labo.

Le problème est que le changement de direction de la seconde condition à la première est extrêmement lent (environ 1 à 2 secondes) mais quasi instantanée de la première à la deuxième.

Le projet nécessite que le moteur change de rotation instantanément dans les deux sens dès que la tension mesuré est trop basse ou trop haute.

merci.

Fournir un schéma de câblage.

stepper ne gere pas step et dir.
https://github.com/arduino-libraries/Stepper

Vous utilisez des variables en float pour target1 et target2 (4.5 et 5.5)

Cependant

en prenant voltage comme un int, vous abandonnez la partie fractionnaire de la tension et travaillez avec un nombre entier. ça vous fait perdre en précision et il faudra plus de temps pour passer le seuil. (dit autrement, si vous êtes en théorie à 4.99 l'arrondi vous fait tomber directement à 4 et donc sous target1 alors qu'il faudra dépasser 6 pour être supérieur à target2)

essayez de passer voltage simplement en float et écrivez

  float voltage = map(value, 0, 1024, 0, 2500);
  voltage /= 98.0; // Conversion correcte de l'échelle de voltage

dites nous si ça fait une différence


stepper sait faire step. Je ne vois pas dir dans le code...

Bonjour

La direction est donnée par des pas positifs ou négatifs.

		myStepper.step(stepsPerRevolution);
		myStepper.step(-stepsPerRevolution);

De toute façon, comme le signale @59jag

Il faut prendre StepperDriver ou AccelStepper pour utiliser STEP et DIR.

Pour information, voici une vue de l'oscilloscope de STEP et DIR (en rouge).

Cordialement
jpbbricole

Oui - donc je ne comprends pas trop le point sur step et dir

map travaille avec des entiers, donc map n'apporte rien il ne rajoute pas des pas. Et ensuite tu divises par 98.
Autant faire directement la conversion en une seule étape et en travaillant avec des float.
float voltage = value * 24.9e-3


A noter, par défaut, la référence de l'ADC sur les cartes Arduino c'est l'alimentation 5V. Donc, elle peut être bruitée et elle peut dériver. De plus, si on change d'alimentation, comme lorsqu'on passe du PC à un équipement en boite par exemple, ce 5V va changer. Il est souvent spécifié à ±5%. Ceci peut être la cause d'un dysfonctionnement de ton projet car du coup, tes seuils ne seront plus corrects.
Solutions:

  • utiliser la référence interne de l'ATmega. Elle n'est pas très précise, elle est spécifiée à ±10%, mais elle ne bougera plus par la suite. Elle est aussi de 1.1V typique ce qui t'obligera à adapter ton pont diviseur.
  • utiliser une référence externe.

au debut c'etait bien une float. je l'ai passé en int pour que la carte fasse peut être moins de calcul , malheureusement aucune différence. j'ai aussi essayé valeur double pareil.

Le code de loop() est très court et il doit s'exécuter plusieurs centaines de fois par secondes, sans doute plus rapidement que le temps de réaction de ton moteur.

j'ai essaye directement float voltage = value * 24.9e-3 aucune différence.
La carte arduino uno est alimenté via le pc.

L'alimentation de labo est uniquement connecte au borne de mesure du capteur de tension pour simulé la mesure de tension d'un électrode.

j'ai tente ce code encore plus court pour éventuellement accélérer la mise en route de la première condition if (voltage < target1) , le moteur change toujours de sens quasi instantanément de if à else if mais prend cette fois-ci plus de 4 secondes pour revenir à la première condition est changé le sens de rotation

#include <Stepper.h>

#define Sensorpin A0
#define directionPin 8
#define stepPin 9
#define stepsPerRevolution 800 // Nombre de pas par révolution pour votre moteur

Stepper myStepper(stepsPerRevolution, stepPin, directionPin); 

//24v = 9750
float TARGET = 200;
float target1 = TARGET - 100;
float target2 = TARGET + 100;

void setup() {
  myStepper.setSpeed(400); // Définir la vitesse du moteur 
  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
}

void loop() {
      
   
    float value = analogRead(Sensorpin);
  
   if (value < target1) { 
   myStepper.step(-stepsPerRevolution);
   
   }
   else if(value > target2){ 
    myStepper.step(stepsPerRevolution);
   }

   }   

 

c'est plutôt la carte qui me parait en retard et non le moteur car le moteur change de sens rapidement de "if" à "else if".
c'est comme si la carte prenez énormément de temps pour lire la valeur du capteur de tension et ainsi pouvoir vérifier la première condition.

La carte n'est peut être pas assez performante ?
Je dois utilisé un Arduino DUE plus rapide ?

Tu as vu le post#6 de @ 59jag et le miens #8?
Tu ne peut pas utiliser Stepper.h avec un driver tel que le tiens.
Dans son initialisation Stepper ne demande que le nombre de pas par tour et les bornes des commande des bobines, pas de STEP ni de DIR


Changes avec StepperDriver

Cordialement
jpbbricole

Bonjour uno556

Essaies ça, il faut la bibliothèque StepperDriver.
image

Il est possible que stepperMicroSteps ne soit pas juste.

//#include <Stepper.h>
#include "BasicStepperDriver.h"

#define Sensorpin A0
#define directionPin 8
#define stepPin 9
#define stepsPerRevolution 800 // Nombre de pas par révolution
#define stepperMicroSteps 1
#define stepperRpm 400
//Stepper myStepper(stepsPerRevolution, stepPin, directionPin);
BasicStepperDriver stepper(stepsPerRevolution, directionPin, stepPin);

float TARGET = 5.0;                     // Tension à Maintenir
float target1 = TARGET - 0.5;    // Marge d'erreur 1
float target2 = TARGET + 0.5;   // Marge d'erreur 2


void setup() {
	//myStepper.setSpeed(400); // Définir la vitesse du moteur
    stepper.begin(stepperRpm, stepperMicroSteps);
	pinMode(directionPin, OUTPUT);
	pinMode(stepPin, OUTPUT);
	
}

void loop() {
	
	// Lecture de la valeur du capteur et conversion en tension
	int value = analogRead(Sensorpin);
	int voltage = map(value, 0, 1024, 0, 2500);
	voltage /= 98; // Conversion correcte de l'échelle de voltage

	if (voltage < target1) 
	{
		//myStepper.step(-stepsPerRevolution);
		stepper.move(-stepsPerRevolution);
	}
	else if(voltage > target2)
	{ 
		//myStepper.step(stepsPerRevolution);
		stepper.move(stepsPerRevolution);
	}	
}

PS: Pour "pinailler", ce n'est pas value, 0, 1024, 0, 2500); mais value, 0, 1023, 0, 2500); :wink:

Cordialement
jpbbricole

Bonjour, jpbbricole
j'ai tenté ton script le moteur tourne un peu mieux avec cette bibliothèque mais toujours le même problème qu'au début.

Le moteur change rapidement de sens entre la condition "if à "else if" mais prend 2 secondes à revenir à la première condition et pendant ce temps le moteur continu de tourné dans le mauvais sens pendant 2 secondes avant de changé de sens, crash assuré. Plus la vitesse du moteur est elevée, plus il fera de tour en trop, le réglage vitesse n'affecte pas la durée d'environ 2 secondes.

j'ai tenté ce script , même problème.

#include <BasicStepperDriver.h>

#define Sensorpin A0
#define dirPin 8
#define stepPin 9
#define stepsPerRevolution 800 // Nombre de pas par révolution pour votre moteur

BasicStepperDriver myStepper(stepsPerRevolution, dirPin, stepPin);

float target1 = 5;
float target2 = 6;

void setup() {
  myStepper.begin(40, 8); // Définir la vitesse du moteur (400 tr/min) et le microstepping 
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
}

void loop() {
  // Lecture de la valeur du capteur et conversion en tension
  int value = analogRead(Sensorpin);
  float voltage = map(value, 0, 1023, 0, 2500);
  voltage /= 98; // Conversion correcte de l'échelle de voltage

  // Conditions pour ajuster la rotation
  if (voltage < target1) {
    myStepper.move(stepsPerRevolution); // Rotation 
  } else if (voltage > target2) {
    myStepper.move(-stepsPerRevolution); // Rotation inverse
  } else {
    myStepper.stop(); // Arrêter le moteur
  }
}

ah j'avais raté

je ne comprenais pas à quoi il était fait référence


En fait ça dépend de ce que l'on veut faire — on pourrait aussi écrire (value, 0, 1024, 0, 2501); ça joue sur la tête de la fonction affine par morceau

le mieux sans doute c'est de mettre value *( 2500.0 / 1023.0) et ne pas utiliser map()

:slight_smile:

Bonjour uno556

Pour voir si tu peux diminuer cette latence essaies ceci:

		stepper.move(-stepsPerRevolution/10);
		stepper.move(stepsPerRevolution/10);

Voir même /20.
Et toujours avec la bibliothèque StepperDriver.

Après je t'expliquerai, si ça corrige, le fond ma réflexion :wink:

Cordialement
jpbbricole