Commande PWM moteur CC, lecture encodeur
Bonjour,
Je débute en Arduino, et j'essaie d'identifier expérimentalement un moto-réducteur CC muni d'un encodeur.
La manip de base consiste à imposer une tension d'alimentation et de recueillir les informations du codeur pour tracer la vitesse en fonction du temps.
On en déduit le gain statique et la constante de temps, en assimilant le moteur à un premier ordre.
Moteur CC 6V, réducteur au 1/53, codeur 2 voies à 6 ticks par tour chaque.
Je considère que je ne loupe aucun tick, vu que je ne fais rien dans la loop, mais je fais des trucs dans la gestion de l'interruption
je calcule et affiche la vitesse de l'arbre réducteur en tr/min sur la voie série
Programme ci-dessous :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
// Faire tourner le moteur à une vitesse constante
// Récupérer chaque changement d'état grace à une interruption sur l'une des 2 voies
// Calculer la vitesse du réducteur en tr/min et l'afficher sur la liaison série
const int _MOTEUR = 9; // Digital pin pour commande moteur
unsigned long temps; // variable de temps en microsecondes, car avec micros() direct, ça marche pas !!
unsigned long tempsinit; // instant initial
float vitesse ;
/* Routine d'initialisation */
void setup() {
pinMode(_MOTEUR, OUTPUT); // Configuration de la broche en sortie
analogWrite(_MOTEUR, 255); // Commande PWM de 0 à 255 Max (de 0 à 100% de la "tension d'alimentation")
delay(5000); // Pause de 5 sec pour laisser le temps au moteur de s'arréter si celui-ci est en marche
attachInterrupt(0, compteur, CHANGE); // Interruption sur tick de la codeuse (interruption 0 = pin2 arduino mega)
Serial.begin(230400) ;
tempsinit = micros();
}
/* Fonction principale */
void loop(){
}
/* Interruption sur tick de la codeuse */
void compteur(){
temps = micros();
vitesse = (1000000/float(temps-tempsinit))*60/6/53 ;
Serial.println(vitesse);
tempsinit=temps;
} |
Pb : quand je change la valeur du PWM (typiquement : 127 au lieu de 255)
la vitesse ne change pas en proportion.
Qu'est-ce que je loupe ?
Par avance, merci de votre aide
La même chose avec un motorshield
Suite aux réponses précédentes, je me suis demandé si le problème ne venait pas du matériel.
Jusqu'à présent, je ne m'étais même pas posé la question...
J'ai changé de carte arduino, je l'ai associée à un motorshield
J'ai fait les branchements sur la voie B (alimentation moteur)
Le programme est identique au précédent, aux spécificités du motorshield (Brake, notamment)
...
Les résultats sont les mêmes. Le PWM ne semble pas délivrer une tension proportionnelle au rapport cyclique.
Je me base sur une comparaison simple : l'alimentation en direct, avec PWM=255, en 3, 4.5 et 6V donne
respectivement : 78, 114, 154, soit 50.6%, 74% et 100%
Donc là, la vitesse en RP est presque proportionnelle à la tension d'alimentation.
Ce qui n'est pas le cas quand je commande avec un PWM différent de 255
Par avance, merci pour des avis qui pourraient expliquer ce comportement
Cordialement
Horus68
Autre programme avec le PmodHB5
Pour éviter de faire un Serial.print dans la routine de gestion d'interruption,
j'ai essayé de remplir un tableau avec les valeurs, pour le faire lire seulement après.
J'ai réussi grâce aux conseils avisés de jpbbricole : le "volatile" est la clef
Le comportement ne semble pas très différent. Mais, avec les données remontées, on peut noter une forte différence de temps de réponse,
alors que théoriquement, ça ne dois pas être le cas...
Le programme :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| // Faire tourner le moteur à une vitesse constante, sauf démarrage
// Récupérer chaque changement d'état grace à une interruption chaque voie du codeur
// Calculer la vitesse du réducteur en tr/min et la stocker dans un tableau
// Transmettre a posteriori via la voie série
const int nbTicks = 96;
const int _MOTEUR = 9; // Digital pin pour commande moteur
unsigned int tick_codeuse = 0; // Compteur de tick de la codeuse
unsigned long Old_tick_codeuse = 0; // Ancienne valeur de tick de la codeuse
unsigned long Millis_tick_codeuse = 0; // Ancien instant de tick de la codeuse
unsigned long temps; // variable de temps en microsecondes, car avec micros() direct, ça marche pas !!
unsigned long temps_ant; // instant antérieur
unsigned long timeinit; // instant initial
volatile float vitesse;
volatile float periode;
volatile float vitesses[nbTicks][2];
volatile bool vide = true ;
volatile int i = 0 ;
/* Routine d'initialisation */
void setup() {
pinMode(_MOTEUR, OUTPUT); // Configuration de la broche en sortie
analogWrite(_MOTEUR, 127); // Commande PWM de 0 à 255 Max (de 0 à 100% de la "tension d'alimentation")
attachInterrupt(0, compteur, CHANGE); // Interruption sur tick de la codeuse (interruption 0 = pin2 arduino uno)
attachInterrupt(1, compteur, CHANGE); // Interruption sur tick de la codeuse (interruption 1 = pin3 arduino uno)
Serial.begin(230400) ;
Serial.flush();
delay(5000); // Pause de 5 sec pour laisser le temps au Serial de s'initialiser
timeinit = micros();
temps_ant = timeinit ;
}
/* Fonction principale */
void loop(){
while (vide){
}
if (not vide){
Serial.println("Tableau des vitesses");
for (int j=0 ; j<nbTicks ; j++){
Serial.print(vitesses[j][0]); Serial.print(", ");Serial.println(vitesses[j][1]);
vide = true ;
}
}
}
/* Interruption sur tick de la codeuse */
void compteur(){
// Old_tick_codeuse = tick_codeuse ; // mémorise l'ancien instant
tick_codeuse++; // On incrémente le nombre de tick de la codeuse
temps = micros();
// periode = float(temps-temps_ant)/1000;
if (i<nbTicks){
vitesse = 1000000.0/float(temps-temps_ant)*60/12/53 ;
vitesses[i][0]= (temps-timeinit) ; vitesses[i][1]= vitesse ;
temps_ant=temps;
// Serial.print("i= "); Serial.print(i); Serial.print(", ");
// Serial.println(vitesse);
i++ ;
}
else {
analogWrite(_MOTEUR, 0);
vide = false;
// Serial.println(vitesse);
// Serial.print(" , ");
// Serial.println(tick_codeuse);
}
} |