Go Down

Topic: Retour au neutre d'un moteur (Read 399 times) previous topic - next topic

joedu47

Bonjour à toute et à tous.

Je me permet de demander votre car je bloque sur ce sujet.
Le projet sur lequel je travail actuellement est un volant qui oppose une résistance lors d'un mouvement.
L'idée est qu'il retourne au neutre lorsque l'on relâche le volant.
Pour la lecture, un potar sur l'axe de direction, un arduino ou autre, un pont en H et le moteur.
Je précise qu'il est 100% autonome.

En ce qui concerne l'électronique, je n'ai pas problème, je gère mais le code pour cette fonction je bloque.

Merci par avance pour l'éclairage et de votre aide.

Romuald

joedu47

Re.bonjour
J'ai en tête la consigne pour ce bout de code, je vais essayé de mettre tout ça par écrit le plus explicitement possible !

Alors mon idée que je passe en traduction :

valeur du potar : 0-1023
la moitié          : 1023/2 = ~511

Si je tourne à gauche : moitié (511) - ma valeur x
Si je tourne à droite   : moitié + ma valeur y
Au neutre = moitié

Idéalement, j'aimerai pouvoir enregistrer la valeur mini/maxi lors d'une initialisation, recherche de butées par exemple afin de l'utiliser dans le reste du programme et de faire qu'il soit adaptable sur tout support.

Merci

Romuald



 

lesept

As-tu des notions de programmation sur Arduino ? Si non, tu peux commencer par lire des tutos (Openclassrooms, Eskimon) qui te donneront les bases, notamment comment s'organise un programme.

Dans ton cas, il faut lire la position du potentiomètre et appliquer cette consigne au moteur, si j'ai bien compris. Je ne m'y connais pas beaucoup en moteurs, mais j'ai l'impression que tu parles plutôt d'un servomoteur. (Kammo : Help !)

Différence : on peut imposer une position à un servo, on peut juste imposer une vitesse à un moteur.

La lecture du potard se fait simplement : après avoir déclaré la broche sur laquelle il est branché :
Code: [Select]
int position = analogRead(broche_potard);

Pour la consigne au servo, il faut transformer cette valeur lue en une valeur à appliquer. Le plus simple est d'utiliser la fonction map.
Code: [Select]
Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow,
a value of fromHigh to toHigh, values in-between to values in-between, etc.
Syntax:
map(value, fromLow, fromHigh, toLow, toHigh)


Enfin pour appliquer cette consigne au servo, il faut utiliser les fonctions de la bibliothèque ... servo ! Puisqu'on parle de bibliothèque, il faut aussi que tu apprennes à les installer.

A bientôt sur le forum, avec ton premier code !! (lis les messages épinglés en haut du forum pour savoir comment le poster)
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

joedu47

Bonjour Lesept,

J'ai quelques notions en programmation.

J'ai écumé les tutos concernant les servos, le principe est le même mais en plus gros ! C'est pour faire bouger un volant (le même principe qu'un retour de force).

 

joedu47

Après avoir compris certaines choses, un bout de code, dites moi ce que vous en penser

Code: [Select]

#define potard A0 // pin du potentiomètre
#define out1 9    // pin de la sortie pour le pont en H
#define out2 10   // pin de la sortie du pont en H
#define zone 10   // varible de la zone neutre pour éviter les oscilations
#define max_speed 130 // vitesse max du moteur en PWM

int cal, vitesse; // calibration de l'axe et de la vitesse


void setup() {
  pinMode(out1, OUTPUT);
  pinMode(out2, OUTPUT);

cal = analogRead(potard); // calibration de la valeur

}

void loop() {
int raw;

// mesure de la valeur brut
raw = analogRead(potard) - cal;

// moteur à l'arrêt si zone neutre
if (raw >- zone && raw < zone) {
  vitesse = 0;
}
else if (raw >= 0){ // sinon on revient au neutre, on recule
analogWrite(out1, LOW);
analogWrite(out2, HIGH);
vitesse = map(raw, 0, 1023 - cal, 0, max_speed);
}

else if (raw < 0){ // sinon on revient au neutre, on avance
analogWrite(out1,HIGH);
analogWrite(out2, LOW);
vitesse = map(raw, 0, cal, 0, max_speed);
}
// consigne de la vitesse mini
if (vitesse < 70) {
  vitesse = 0;
}

// Sortie avec signal PWM
analogWrite(out1, vitesse);
analogWrite(out2, vitesse);
}

lesept

A vrai dire : pas grand chose, car (comme je l'ai dit plus haut) "Je ne m'y connais pas beaucoup en moteurs"...

Je continue de penser que si tu cherches à ramener le volant à une position donnée (position centrale ou neutre), c'est un servomoteur que tu dois utiliser et pas un moteur. En l'état de ton code s'il est correct (ce qui n'est pas sûr), le moteur va tourner à la vitesse que tu lui indiques avec le potard, mais il n'a aucune raison de s'arrêter.

Pour contrôler un moteur, il te faut du matos : regarde ce tuto (en 2 parties).

Par contre, tu peux lui ajouter un codeur de position et l'arrêter lorsqu'il arrive à la position désirée. En cherchant sur G**gle "Arduino codeur position" tu trouveras de la doc.
Pour que le moteur s'arrête "gentiment" (pas trop brusquement), il faudra peut-être ajouter un régulateur PID (c'est du soft, pas de panique), mais c'est pas forcé...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

joedu47

Merci pour le lien, je l'ai déjà vu/étudié.

Le problème avec un servomoteur, que je connais bien (modélisme) est que l'on ne peut pas le contrer sans devoir le faire surchauffer, ou voir casser le palonnier, ou autre. J'y ai pensé.

Les fabricants de volant à retour de force utilisent ce principe, un moteur DC mabuchi, un pont en H, un potard, une réduction pour le couple moteur avec comme gestion  2 fonctions :
 - 1 par logiciel, le jeu envoie les données angulaire
 - 2 autonome, le potard envoie la position angulaire avec le contre et le retour au centre

Tu peux me poser cette question : " Pourquoi ne pas utiliser un volant tout fait ?"

Et je réponds : "Ba, si c'est trop simple et ne pas se creuser la tête, ce n'est pas intéressant !"

Le projet repose sur une problématique qu'un ami m'a posé, le volant est de conception perso, avec une interface de chez leo, il veut une résistance lorsqu'il tourne le volant et surtout pouvoir le régler comme bon lui semble.

Christian_R

Et pourquoi pas utiliser un ressort ?  :smiley-mr-green:
Christian

joedu47

Bonjour,

Alors suite de mon projet

Le code me permettant de revenir au centre. Toute fois, il faut que le potard soit au centre lors du démarrage
ou sinon faire un reset avec le potard centré.

Code: [Select]

#define potard A0 // pin du potentiomètre
#define out1 9     // pin de la sortie pour le pont en H
#define out2 10   // pin de la sortie du pont en H
#define en1 3      // pin de la commande "Enable" dans le cas d'un shield
#define zone 20   // variable de la zone neutre pour éviter les oscillations
#define max_speed 130 // vitesse max du moteur en PWM

int cal, vitesse; // calibration de l'axe et de la vitesse


void setup() {
  pinMode(out1, OUTPUT);
  pinMode(out2, OUTPUT);
  pinMode(en1, OUTPUT);

cal = analogRead(potard); // calibration de la valeur

}

void loop() {
int raw, raw1;

// mesure de la valeur brut
raw = analogRead(potard)-cal;
raw1 = zone + cal;
// moteur à l'arrêt si zone neutre
if (raw > -zone && raw < zone) {
  vitesse = 0;
  digitalWrite(out1,LOW);
  digitalWrite(out2,LOW);
  digitalWrite(en1, LOW);
}
else if (raw >= 0){ // sinon on revient au neutre, on recule
digitalWrite(out1, LOW);
digitalWrite(out2, HIGH);
vitesse = map(raw, 0, 1023 - raw1, 0, max_speed);

}

else if (raw < 0){ // sinon on revient au neutre, on avance
digitalWrite(out1,HIGH);
digitalWrite(out2, LOW);
vitesse = map(raw, 0,raw1 - 1023, 0, max_speed);

}
/*// consigne de la vitesse mini
if (vitesse < 70) {
  vitesse = 0;
}
*/
// Sortie avec signal PWM
analogWrite(en1, vitesse);

}

lesept

Il revient au centre en tournant autour, par petits à coups droite - gauche ?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

fdufnews

#10
May 26, 2018, 10:42 pm Last Edit: May 26, 2018, 10:42 pm by fdufnews
Le code me permettant de revenir au centre. Toute fois, il faut que le potard soit au centre lors du démarrage
ou sinon faire un reset avec le potard centré.
Il faudrait faire une fonction de calibration, qui releve la valeur du potentiomètre lorsque le moteur est à la position neutre  sauve cette valeur dans la flash ce qui éviterait de devoir la refaire à chaque démarrage (à lancer "en fabrication"). Eventuellement, si tu constates des dérives dans le temps, ce qui ne serait pas très surprenant, tu peux mettre en place un moyen de lancer cette calibration à la demande.

joedu47

#11
May 27, 2018, 02:36 pm Last Edit: May 27, 2018, 02:38 pm by joedu47
Bonjour,
La suite de du projet en concluant pour moi, en effet, pour répondre à réflexion sur le retour au neutre, je l'ai fait, un peu brouillon, mais ça fonctionne !

Le bout de code :

Code: [Select]

#define potard A0 // pin du potentiomètre
#define out1 9     // pin de la sortie pour le pont en H
#define out2 10   // pin de la sortie du pont en H
#define en1 3
#define zone 30   // varible de la zone neutre pour éviter les oscilations
#define max_speed 250 // vitesse max du moteur en PWM

int cal, milieu, mini, maxi, vitesse; // calibration de l'axe et de la vitesse, du centre

void test (){

    digitalWrite(out1, LOW);
    digitalWrite(out2, HIGH);
    analogWrite(en1, max_speed);
    delay(2000);
    mini = analogRead(potard);

    digitalWrite(out1, HIGH);
    digitalWrite(out2, LOW);
    analogWrite(en1, max_speed);
    delay(2000);
    maxi = analogRead(potard);

 delay(2500);
  milieu = (mini + maxi)/2;
}


void setup() {
  pinMode(out1, OUTPUT);
  pinMode(out2, OUTPUT);
  pinMode(en1, OUTPUT);
test();
cal = milieu; // calibration de la valeur

}

void loop() {
int raw, raw1;

// mesure de la valeur brut
raw = analogRead(potard)-cal;
raw1 = zone + cal;
// moteur à l'arrêt si zone neutre
if (raw > -zone && raw < zone) {
  vitesse = 0;
  digitalWrite(out1,LOW);
  digitalWrite(out2,LOW);
  digitalWrite(en1, LOW);
}
else if (raw >= 0){ // sinon on revient au neutre, on recule
digitalWrite(out1, LOW);
digitalWrite(out2, HIGH);
vitesse = map(raw, 0, 1023 - cal, raw, max_speed);
//analogWrite(en1, vitesse);
}

else if (raw < 0){ // sinon on revient au neutre, on avance
digitalWrite(out1,HIGH);
digitalWrite(out2, LOW);
vitesse = map(raw, 0,cal - 1023, -raw, max_speed);
//analogWrite(en1, vitesse);
}
/*// consigne de la vitesse mini
if (vitesse < 70) {
  vitesse = 0;
}
*/
// Sortie avec signal PWM
analogWrite(en1, vitesse);
//analogWrite(out2, vitesse);
}


petite précision, le montage fonctionne en l'état, seul bémol, le L298 pas assez costaud !!!

joedu47

Re bonjour,

Après quelques réflexions de ma part, mon cerveau fume en ce moment !

Donc cela concerne le PWM, quelques recherches plus tard (au passage je remercie les auteurs des articles), le PWM utilisé dans mon projet est limité en fréquence, 500 Hertz, d'ou le sifflement du moteur, fort désagréable...

Et la, bang ! Pourquoi ne pas augmenter la fréquence du PWM en sortie avec le TIMER inclue dans le micro controleur, je fais référence à ceci : http://playground.arduino.cc/Code/PwmFrequency

Pour la sortie j'utilise la sortie 3, qui est TCCR2B, la fréquence est de 31250 Hertz, plus que suffisant car après lecture des datasheets, L298 entre autre, la valeur préconisée est de 25000 Hertz.

Maintenant, si j'ai bien tout compris, il me suffit de déclarer TCCR2B = TCCR2B & 0b11111000 | 0X01; dans le setup et le tour est joué !?

Biensur, je déclare une valeur maxi a ne pas dépasser !

Dites moi si j'ai juste

Joe


Go Up