hysteresis moteur DC et potentiometre

Bonjour a tous,
je débute donc SVP soyez indulgent lol :slight_smile:
je rencontre un problème sur l'application d'un hysteresis.
j'ai (je pense) bien compris a quoi sa sert mais je butte sur son application concrete.
Le but de mon montage est de contrôler un moteur DC (avec engrenages) via un potentiomètre pour le "feedback".
Le sketch fonctionne mais le moteur une fois arrivé en position x (0-360°) se met a trembler car il oscille je pense entre la commande "avant" et "arrière".
Normalement c'est là qu'intervient l'hyseteris, de façon à allouer une plage de tolérance.
je vous joint mon sketch afin de m'aiguiller vers une solution.
merci

// controle moteur DC avec valeur cible et lecture sur un potentiometre de l'ange exercé

#include <AFMotor.h>

AF_DCMotor motor(2, MOTOR12_64KHZ);// create motor #2, 64KHz pwm
 
int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin 
int valeurcible =10;
int hyseteris =2;


void setup() 
{ 
 motor.setSpeed(80);     // set the speed to 200/255

} 
 
void loop() 
{ 
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023) 
  val = map(val, 1, 1023, 1, 360);     // scale it to use it with the servo (value between 0 and 180) 

  
  if (valeurcible < val) { motor.run(FORWARD);}                                        //moteur avance
 else if (valeurcible > val) { motor.run(BACKWARD);}                                  // moteur recule
 
  else if (valeurcible >= (val+ hyseteris)) motor.run(RELEASE);                      //moteur stop
    else if (valeurcible <= (val- hyseteris)) motor.run(RELEASE);                   //moteur stop
     else if (valeurcible == val) motor.run(RELEASE);                              //moteur stop
    
}

Je n'ai pas regardé ton code parce qu'en priorité je me pose de suite une question matérielle :
Quel potentiomètre utilise-tu pour l'information de retour d'asservissement ?

Il existe des potentiomètres qui ont réellement une course de 0/360degrès mais ce ne sont pas les plus courants et ils sont chers, en général c'est 270 degrès électrique et 300 degrès mécanique.
A tu essayé ton code en réduisant la plage de variation ?

Il y a une erreur dans ton code... Puisqu'avant de tester l'hystérésis, tu fais une comparaison brute... essaie cela, pas de comparaison brute, directement hystérésis :

void loop() 
{ 
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023) 
  val = map(val, 1, 1023, 1, 360);     // scale it to use it with the servo (value between 0 and 180) 

  
  if (valeurcible < (val - hyseteris)) { motor.run(FORWARD);}                                        //moteur avance
 else if (valeurcible > (val + hyseteris)) { motor.run(BACKWARD);}                                  // moteur recule
    else {motor.run(RELEASE);}
 
}

A supposer que hyseteris soit toujours positif... le moteur ne tournera que si valeurcible sort de l'intervalle [val - hyseteris, val + hyseteris] et s'arrêtera dès que l'intervalle entoure valeurcible.

Prévois un hyseteresis assez grand au début, genre 500, tu le réduiras au fur et à mesure de tes tests. Si tu es motivé, colle un second potar sur une entrée analogique et fais un "hyseteresis = analogread(hyst_pin) / 2; Serial.println(hyseteresis);", comme ça, pas besoin de reloader le prog à chaque test, tu liras la valeur du bon hyseteresis sur ta console!

je te souhaite un bon courrage pour ton asservissement, car ce n'est pas simple. [HUMOUR]Tu savais qu'il existe des servomoteurs?[/HUMOUR] :grin:

Super_Cinci:
Il y a une erreur dans ton code... Puisqu'avant de tester l'hystérésis, tu fais une comparaison brute... essaie cela, pas de comparaison brute, directement hystérésis :

void loop() 

{
 val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
 val = map(val, 1, 1023, 1, 360);     // scale it to use it with the servo (value between 0 and 180)

if (valeurcible < (val - hyseteris)) { motor.run(FORWARD);}                                        //moteur avance
else if (valeurcible > (val + hyseteris)) { motor.run(BACKWARD);}                                  // moteur recule
   else {motor.run(RELEASE);}

}



A supposer que hyseteris soit toujours positif... le moteur ne tournera que si valeurcible sort de l'intervalle [val - hyseteris, val + hyseteris] et s'arrêtera dès que l'intervalle entoure valeurcible.

Prévois un hyseteresis assez grand au début, genre 500, tu le réduiras au fur et à mesure de tes tests. Si tu es motivé, colle un second potar sur une entrée analogique et fais un "hyseteresis = analogread(hyst_pin) / 2; Serial.println(hyseteresis);", comme ça, pas besoin de reloader le prog à chaque test, tu liras la valeur du bon hyseteresis sur ta console!

je te souhaite un bon courrage pour ton asservissement, car ce n'est pas simple. [HUMOUR]Tu savais qu'il existe des servomoteurs?[/HUMOUR] :grin:

Merci Super_Cinci,
oui je sais qu'il existe des servomoteur, j'en ai, dont un qui fait 30kg de torq. Mais pour certains projets, cela ne convient pas exactement.
En ce moment je dispose d'un moteur DC assez puissant (recup donc pas de datasheet/ rien écrit dessus) , il a un paquet d'engrenages digne d'un servo mais d'une taille bien plus imposante et un couple difficilement "stoppable" à la main. Tu me dira idem pour le servo de 30kg, sauf qu'en changeant le potar par un 10 tours, je pourrais avoir un "feedback" precis tout en faisant du 360° et plus avec peu de conso électrique car j'utilise un L298 (2 ampères).
En me relisant je suis pas sur d'être tres clair.?. :cold_sweat:
Prochaine étape, si ta correction fonctionne (je n'ai pas de doute la dessus): encodeur rotatif absolu grey code.
après sa je me re-pencherais sur l'asservissement PID via un encodeur optique en quadrature couplé à un moteur d'essuie glace et donc je devrais (et solliciterais surement de l'aide ici) créer un pont en H avec des transistors puissants , je pense a des MSOFET pour avoir quelque chose de l'ordre de 30A sous 12V environ. Bref, plein de projets en tete mais pas assez de temps pour tous réaliser.
Merci encore pour ton aide, je te tien au courant pour ce qui est du fonctionnement du code.

68tjs:
Je n'ai pas regardé ton code parce qu'en priorité je me pose de suite une question matérielle :
Quel potentiomètre utilise-tu pour l'information de retour d'asservissement ?

Il existe des potentiomètres qui ont réellement une course de 0/360degrès mais ce ne sont pas les plus courants et ils sont chers, en général c'est 270 degrès électrique et 300 degrès mécanique.
A tu essayé ton code en réduisant la plage de variation ?

Bonjour 68tjs,
effectivement j'utilise un potar "de base" 4k7 ohm qui fait un "faux 360°" comme tu le décris si bien. Je vais effectivement essayer de réduire la plage de l'angle, mais j'ai peur que cela ne change pas grand chose car le moteur tremble meme quand il a atteint la valeur cible (et j'ai essayé toutes les position dans la plage). Par contre quand je l'amène dans la "zone morte"(je sais pas comment on dit desolé) je n'ai ni tremblement ni réaction. Par la je veu dire que meme en tournant l'axe à la main, il tourne en roue libre jusqu'au sortir de la zone en question, donc un gros manque de précision mais pas vraiment un amélioration au sens ou on l'entend dans ce cas de figure.
J'essaierais quand meme cette option car elle est logique, meme si ce n'est pas LA solution , sa m'évitera déjà de futures problèmes.
Quoi qu'il en soit, j'apprécie toujours l'aide, les remarques et suggestion et trouve que sur les forums les gens ne remercie pas assez ceux qui les aides. Je trouve cela dommage. Donc a tous ceux qui aident: MERCI 8)

Merci, merci, :grin:
Rassures toi, si on aide c'est qu'on aime cela, en fait nous sommes de grands égoïstes nous nous faisons d'abord plaisir à nous même.
Mais cela fait plaisir d'entendre en retour certaines paroles qui montrent que l'esprit "consommateur" n'a pas réussi à contaminer tout le monde.

Mes propos étaient orientés deboguage mise au point et séparation des variables.
En réduisant la plage de variation et en se limitant a des valeurs "hors des zones à problème potentiel" tu élimine le matériel. Une fois le programme au point tu t'occupes à résoudre le problème matériel.

Sur tes "tremblements" est ce que ton signal de retour est propre ? Au voltmètre tu as peut être une valeur continue constante mais qu'en est-il du bruit que le voltmètre lisse ? Essaye de mettre un condensateur de filtrage.

Un asservissement c'est pas le plus facile à réaliser quand on n'a pas les appareils de mesures adaptés à disposition.
bonne chance

@68tjs:

Bonne idée pour le condensateur! XD
j'ai remarqué qu'en appliquant une resistance mécanique (mes doigts), sur l'arbre primaire le tremblement pouvait s'arrêter. Surement du a un "lissage" a cause de l'inertie et de la latence que cette resistance impose. Un condo peut éventuellement faire la meme chose ?!
Pour ça, Google est mon ami, j'irais voir sa demain car je ne suis plus devant le materiel (je suis préssé d'experiementer ça !!! $))
Quand j'aurais fini de mettre sa au point(grace a vous), je ferais peut être un chti tuto sans prétention.
Pour la bonne raison que j'ai cherché pas mal de trucs liés au controle des moteurs DC et que c'est pas souvent "accessible" au pure-débutant que je suis. Débutant en tout: électronique et programmation. Pour la plupart d'entre vous certaines choses sont acquises depuis trés longtemps donc logiques mais ce n'est pas mon cas. J'espere que sa en aideras certains, du coup je contribuerais a ma façon a agrandir la communauté. :wink:

Merci Super_Cinci SA MARCHE !!!!
grace a ta modification de code, c'est impecable! sa vaut la precision d'un servo modelisme!
en plus sa a plus de puissance et c'est du DIY, je suis aux anges. :grin: :grin: :grin:
Du coup j'ai fait un petit croquis sur Fritzing , je joint le code complet et une photo du moteur réel. J'espere que sa en aidera d'autres.

// controle moteur DC avec valeur cible et lecture sur un potentiometre de l'ange exercé

#include <AFMotor.h>

AF_DCMotor motor(2, MOTOR12_64KHZ);// crée un moteur sur les pin #2 du shield moteur, fréquence (64KHz pwm)
 
int potpin = 0;  //pin analogique A0 pour le potentiometre
int val;    // variable pour la lecture de la valeur analogique
int valeurcible =200; // variable a changer pour changer l'angle du moteur (peut se coupler a un autre potar)
int hyseteris =1; // 1 donne des resultats tres precis et stoppe déjà les tremblement moteur


void setup() 
{ 
 motor.setSpeed(255);     // vitesse du moteur de 1 a 255

} 
 
void loop() 
{ 
  val = analogRead(potpin);            // lis la valeur du potentiometre entre 0 et 1023 
  val = map(val, 1, 1023, 1, 280);     // convertis en 0° a 280° 

  
  if (valeurcible < (val - hyseteris)) { motor.run(FORWARD);}                                        //moteur avance
 else if (valeurcible > (val + hyseteris)) { motor.run(BACKWARD);}                                  // moteur recule
    else {motor.run(RELEASE);}                                                                                  //moteur stoppe 
    
}

Si vous pensez que cela merite un tuto un peu plus complet et accessible , dites le moi et je me ferait une joie de détailler et partager avec photo et procédure pas a pas.

Je dis : oui, vas-y
Sans oublier les photos de la valeur ajoutée des modifications mécaniques.

Voici ma modeste contribution. Bonne lecture. :wink:

tuto moteur DC.pdf (694 KB)

Merci

Yep!

Tuto à déplacer dans la catégorie "Réalisations et Projets Finis", non ?

En tout cas, belle présentation :wink:

@+

Zoroastre.

C'est fait :wink:

merci, c'etais pas vraiment fini, sa ne l'est toujours pas, j'attend vos remarques afin d'améliorer la chose.