Probleme de MESURE vitesse rotation avec capteur à fouche end stop.

Bonjour,
Je n’arrive pas à bien mesurer la vitesse de rotation d’un moteur assigné à vitesse constante.
voici le genre de resultat obtenu:

v_r_t_s : 3.7500
vitesse moyenne lissé du moteur B: 1712
v_r_t_s : 3.0000
vitesse moyenne lissé du moteur B: 1700
v_r_t_s : 2.7500
vitesse moyenne lissé du moteur B: 1675
v_r_t_s : 3.0000
vitesse moyenne lissé du moteur B: 1700
v_r_t_s : 3.7500
vitesse moyenne lissé du moteur B: 1662
v_r_t_s : 3.2500

la Vitesse de la Roue en Tour par Seconde oscille entre 2.75 et 4 ce qui est beaucoup trop!!

J’ai une roue codeuse avec 20 trous donc 40 etats / tours donc je devrais avoir des données plus précises et constantes, mais non!
J’ai alors multipliés ces VRTS puis lissé ces vitesses pour avoir une moyenne afin de contourner ces bugs, mais c’est toujours pas génial!

Si quelqu’un peut m’aider, voici mon programme:

// Bug-fix pour Arduino 1.0.6
#define NOT_AN_INTERRUPT -1
// TACHYMETRE SETUP

#include <SimpleTimer.h>

SimpleTimer timer; // Timer pour échantillonnage

unsigned int tick_codeuse = 0; // Compteur de tick de la codeuse

const int frequence_echantillonnage = 100; // Fréquence d’exécution de l’asservissement
const int rapport_reducteur = 10; // !!! // Rapport entre le nombre de tours de l’arbre moteur et de la roue
const int tick_par_tour_codeuse = 40; //64 tick sur deux capteurs hall, ici on a pris un seul capteur

// // PROGRAM TO SMOOTH PULSATION WITH 20 SAMPLE

// Définition du nombre d’échantillons
// pour le calcul de la moyenne glissante de la vitesse du moteur B

const int nEchantillons = 10; // 10 sample

int echantillon[nEchantillons]; // un tableau pour stocker les échantillons lus
int indice = 0; // l’indice de l’échantillon courant
int total = 0; // la somme des échantillons mémorisés
int moyenne = 0; // la moyenne des échantillons mémorisés // AVERAGE of PULSATION (speed detected))
int vitTB = 0; // echantillon de vitesse à l’instant T du moteur B . (pulsation measured by encodeur of motor B at each T time)

//Ports de commande du moteur B

int motorPin1 = 4;
int motorPin2 = 5;
int enablePin = 6;

//Ports de commande du moteur A

//int motorPin1A = 8;
//int motorPin2A = 3;
//int enablePinA = 7;

//definition des entrées du moteur asservi
int pinInput1 = 8; // Commande de sens moteur, Input 1
int pinInput2 = 3; // Commande de sens moteur, Input 2
const int pinPower = 7; // Commande de vitesse moteur, Output Enabled1

//consigne en tour/s
float consigne_moteur= 2; // Consigne nombre de tours de roue par seconde

// Vitesse du moteur B initialisation// Speed motor B

int state = 0; // vitesse assignée au moteur B par le moniteur serie (speed assigned to motor B by the serial monitor)
//float w= 0; //frequence de B (pulsation of moteur B, not used)
//float acc=0; // acc de B pas utilisé (not used)
int vitMoteurB = 0; /// vitesse moyenne mesuréee du moteur B (average speed measured of motor B

// Vitesse du moteur A initialisation// Speed motor A

// la vitesse du moteur A est proportionnelle à la moyenne de la vitesse captée du moteur B
// the speed of the motor A is proportional to the average of the speed of the motor B (vitMoteurB)

int vitMoteurA = 0; /// vitesse assignée au moteur A qui est “mappé” par rapport à la vitesse du moteur B

/*// init calculs asservissement PID
float erreur_precedente = consigne_moteur; // (en tour/s)
float somme_erreur = 0;

//Definition des constantes du correcteur PID
float kp = 200; // Coefficient proportionnel choisis par tatonnement sur le moniteur. Ce sont les valeurs qui donnaient les meilleures performances
float ki = 5; //5.5; // Coefficient intégrateur
float kd = 100; // Coefficient dérivateur

// int moyenneCA =0; // vitesse moyenne Contrainte pour controler vitesse A // average speed Constraint to control speed A
*/

void setup() {

/* Met la broche en entrée, ici capteur à fourche */
attachInterrupt(0, compteur, CHANGE); // Interruption sur tick de la codeuse (interruption 0 = pin2 arduino)
timer.setInterval(1000/frequence_echantillonnage, asservissement); // Interruption pour calcul du PID et asservissement; toutes les 10ms, on recommence la routine

// On remplit le tableau d’échantillons avec des 0
for (int i = 0; i < nEchantillons; i++) {
echantillon = 0;

  • }*

  • //CONTROLE MOTEUR*

  • // Configuration des ports en mode “sortie”*

  • pinMode(motorPin1, OUTPUT);*

  • pinMode(motorPin2, OUTPUT);*

  • pinMode(enablePin, OUTPUT);*

  • pinMode(pinInput1, OUTPUT);*

  • pinMode(pinInput2, OUTPUT);*

  • pinMode(pinPower, OUTPUT);*

  • // analogWrite(enablePinA, 0); // Initialisation sortie moteur A à 0*

  • //delay(300); // Pause de 0,3 sec pour laisser le temps au moteur de s’arréter si celui-ci est en marche*

  • // Initialisation du port série*

  • Serial.begin(9600);*
    }
    void loop() {

  • timer.run(); //on fait tourner l’horloge*
    // delay(10);
    // CONTROLE MOTEUR B VIA MONITEUR SERIE // CONTROL B MOTOR WITH MONITOR SERIE
    // Pont en H L298N // H BRIDGE L298N

  • if (Serial.available() > 0)*

  • {*

  • state = Serial.parseInt();*

  • //*

  • // Sens du mouvement*

  • //*

  • if (state > 0) // avant*

  • {*

  • digitalWrite(motorPin1, HIGH);*

  • digitalWrite(motorPin2, LOW);*

  • Serial.print("Avant ");*

  • Serial.println(state);*

  • }*

  • else if (state < 0) // arrière*

  • {*

  • digitalWrite(motorPin1, LOW);*

  • digitalWrite(motorPin2, HIGH);*

  • Serial.print("Arriere ");*

  • Serial.println(state);*

  • }*

  • else // Stop (freinage)*

  • {*

  • digitalWrite(motorPin1, HIGH);*

  • digitalWrite(motorPin2, HIGH);*

  • Serial.println(“Stop”);*

  • }*

  • //*

  • // Vitesse du mouvement*

  • //*

  • analogWrite(enablePin, abs(state));*

// delay(1);

  • }*
    }
    void compteur(){
  • tick_codeuse++;*
  • // On incrémente le nombre de tick de la codeuse. un seul sens*
    }
    /* Interruption pour calcul du P */
    void asservissement()
    {
  • // CALUCUL de LA VITESSE de la roue codeuse et plus tard Calcul de l’erreur*

int frequence_codeuse = frequence_echantillonnagetick_codeuse; //100tick_codeuse
float vit_roue_tour_sec = (float)frequence_codeuse/(float)tick_par_tour_codeuse/(float)rapport_reducteur; //(100*tick_codeuse)/40/1

  • float v_r_t_s= abs (vit_roue_tour_sec);*
    int (vitTB)= abs (v_r_t_s*500); // !!! 70 vitesse de la roue à chaque instant // speed at each tick

  • // Réinitialisation du nombre de tick de la codeuse*

  • tick_codeuse=0;*

  • // CALCUL MOYENNE /AVERAGE CALCULATION*

  • // Soustraction de l’echantillon précédent*

  • total = total - echantillon[indice];*

  • // Lecture du capteur*

  • echantillon[indice] = (vitTB);*
    // Serial.print ("echantillion(vitTB) : "); Serial.println (echantillon[indice]);

  • // Ajout du dernier echantillon*

  • total = total + echantillon[indice];*

  • // Incrémentation de l’indice*

  • indice++;*

  • // si on est à la fin du tableau …*

  • if (indice >= nEchantillons) {*

  • // …retour au début*

  • indice = 0;*

  • }*

  • // calcul de la moyenne*

  • moyenne =abs (total / nEchantillons);*

  • Serial.print("vitesse moyenne lissé du moteur B: "); // average speed of motor B*

  • Serial.println(moyenne );*

  • vitMoteurB= (moyenne); // average speed divided per 5 to have good int betwen 50 and 400*

  • vitMoteurA= map (vitMoteurB, 1000, 2200, 100, 250); // map to constrain speed motor bteween 100 and 250*

  • // Normalisation et contrôle du moteur*
    /* if (vitMoteur > 255) {

  • vitMoteur = 255; // sachant que l’on est branché sur un pont en H L293D*

  • }*

  • else if (vitMoteur <0) {*

  • vitMoteur = 0;*
    /* }
    _ */ControlMotorA (vitMoteurA);_
    delay(100);

  • // DEBUG*

  • Serial.print("v_r_t_s : "); Serial.println(v_r_t_s,4); // affiche à gauche la vitesse et à droite l’erreur*
    // Serial.print(" : ");
    // Serial.print(erreur,4);
    // Serial.print("vitMoteurB: "); Serial.println(vitMoteurB);
    // Serial.print("vitMoteurA: "); Serial.println(vitMoteurA);
    }
    void ControlMotorA( int powerRate ){

  • digitalWrite( pinInput1, LOW );*

  • digitalWrite( pinInput2, HIGH );*

  • analogWrite( pinPower, powerRate );*
    }

Bonjour bvking

Où est l'initialisation de la broche compteur en entrée, attachInterrupt(0, compteur, CHANGE); n'assure pas cette fonction, y a-t-il une résistance pull-up sur le circuit, sinon initialiser le port avec pinmode(compteur, PULL_UP).

Cordialement
jpbbricole

Bonsoir,

En effet, j'ai vu un programme de tachymetre sans attachinterrupt où l'on prend n'importe qu'elle pin declare en INPUT-PULLUP.

Mais, j'ai toujours un probleme.

J'ai meme dû convertir les vitesses mesurées par leur valeur absolue car j'avais leur exact opposé. Et pareil pour calculer la moyenne de ces mesures.

J'ai plusieurs petits bugs.

Malgré tout, je crois que mon probleme de mesure est moindre quand la vitesse est lente, mais c'est quand même pas normal.

En ajoutant ou retirant des delays dans la boucle asservissement, j'ai des moyennes lissés tout à fait différente.

Est ce que le capteur opto endstop est fiable pour mesurer des vitesses?

Merci, tous conseils sont bienvenues.

bvking:
...
Est ce que le capteur opto endstop est fiable pour mesurer des vitesses?

Bonsoir
Attention à une chose avec les capteurs optiques dans la mesure où tu exploite une interruption en mode "CHANGE"
Il existe un peu l'equivalent des "rebonds mecaniques" autour de la zone de transition optique ,
tu peux donc te retrouver avec plusieurs "CHANGE" rapide avant d'etre en etat stable

bvking:
Bonsoir,

En effet, j'ai vu un programme de tachymetre sans attachinterrupt où l'on prend n'importe qu'elle pin declare en INPUT-PULLUP.

C'est pas ce que je voulais dire, même la pin que tu mets en attachinterrupt doit être déclarée par pinmode(compteur, INPUT_PULLUP)

La fourche optique est tout à fait valable pour ce travail.

Je ne vois pas l'intérêt de déclencher l'interruption en mode CHANGE, ça double (flanc montant et flanc descendant inutilement les interruptions.
Pour ce genre de travail, FALLING ou RISING suffit amplement

Cordialement
jpbbricole

C'est pas ce que je voulais dire, même la pin que tu mets en attachinterrupt doit être déclarée par pinmode(compteur, INPUT_PULLUP)

Je croyais qu'il n'y avait pas besoin de declarer la pin de attachinterrupt car c'était forcement la pin2 ou la pin3.

Ou/Et que c'était géré par la biblio simpletimer qui gère l'attachinterrupt.

J'ai quand même mis pinMode(compteur, INPUT_PULLUP); dans le setup mais ça change rien au resultat.

(par compte quand j'ai declaré dans les constantes, int compteur=2; j'ai eu un message d'erreur car la variable est deja declarée et utilisée par void compteur, et par la biblio simpletimer j'imagine??)

J'ai aussi lissé les données de la vitesse en faisant la moyenne sur 20 echantillons et pas seulmeent 10 et quand je retire le capteur, la moyenne calculée augmente pour enfin redescendre à zero. Je comprends plus rien.

Dois je passer par un moteur avec un codeur incrémental intégré pour être sûr de son fonctionnement.

Le but etant de mesurer la vitesse du moteur. Que je freinerai jusqu'à zero ( et facultativement pourquoi pas inverser le sens de rotation).
Avec cette mesure je desire controler la vitesse de d'autres moteurs (proportionnellement à la vitesse captée).

Merci pour vos idees à venir.

bvking:
Je croyais qu'il n'y avait pas besoin de declarer la pin de attachinterrupt car c'était forcement la pin2 ou la pin3.

Ou/Et que c'était géré par la biblio simpletimer qui gère l'attachinterrupt.

Si on réfléchi, si attachInterrupt faisait la définition du port, comment on lui dirait si on veut INPUT ou INPU_PULLUP
attachInterrupt rattache une pin de l'arduino (avec atribut interrupt) une fonction à exécuter lors de l'événement.
La bibliothèque simpleTimer s'occupe de sa propre interruption.

Pour ce qui est de la déclaration de int compteur ça n'est pas possible tu a déjà une void compteur() donc même nom et ça ne peut êtreen aucun cas utilisé par une bibliothèque.

Pour ce qui est de la stabilité de la mesure, je trouve que tu mesures trop féquemment, j'essayerai 10x -vite.

Cordialement
jpbbricole

Cher jpbbricole!
J'ai fait comme vous avez dit mais ça change rien.
Toutefois en mesurant un certain temps et grâce surtout au lissage de la moyenne, j'obtiens plus ou moins une vitesse constante.
Comme on voit ici:
echantillion(indice) : 197
vitesse moyenne du moteur B: 168
vit_roue_tour_sec : 1.9737
vitMoteur : 33
vitMoteurA : 85
echantillion(indice) : 131
vitesse moyenne du moteur B: 166
vit_roue_tour_sec : 1.3158
vitMoteur : 33
vitMoteurA : 85
echantillion(indice) : 118
vitesse moyenne du moteur B: 164
vit_roue_tour_sec : 1.1842
vitMoteur : 32
vitMoteurA : 85
echantillion(indice) : 157
vitesse moyenne du moteur B: 162
vit_roue_tour_sec : 1.5789
vitMoteur : 32
vitMoteurA : 85
echantillion(indice) : 171
vitesse moyenne du moteur B: 162
vit_roue_tour_sec : 1.7105
vitMoteur : 32
vitMoteurA : 85
echantillion(indice) : 157
vitesse moyenne du moteur B: 162
vit_roue_tour_sec : 1.5789
vitMoteur : 32
vitMoteurA : 85

Dans mon projet, j'ai besoin de savoir la vitesse du premier moteur vitMoteur avec beaucoup plus de precision et plus en "temps réel". Car la vitesse de vitMoteur doit assigner avec le moins de latence possible la vitesse du moteur A.

Je pense que Artouste a raison quand il dit: "Il existe un peu l'equivalent des "rebonds mecaniques" autour de la zone de transition optique ,tu peux donc te retrouver avec plusieurs "CHANGE" rapide avant d'etre en etat stable"

Est-ce que avec une roue codeuse avec beaucoup de fente, j'aurai un resultat plus precis?
Mais quand je freine la vitesse de vitMoteur, n'aurai je pas encore des problemes de rebond?

N'y a t'il pas des moteurs avec encodeurs de bonne qualité pour mon projet à savoir capter la vitesse d'un moteur tournant de 5 à 0 tours par secondes?

Merci pour vos propositions

Bonjour

Il y a ce type de capteur "laser"

Cordialement
jpbbricole

Oui ça à l'air bien le lazer, mais 50 jours de livraison c'est beaucoup.
Dommage que je ne puisse pas utiliser un simple capteur optique.
Peut être quand utilisant une roue codeuse avec plein de fente, j'aurai un meilleur resultat, non?
Quand pensez vous? pour les rebonds..

Si ton moteur tourne doucement, il vaut mieux mesurer la période du signal que sa fréquence.
La fréquence étant faible la mesure ne sera précise que sur un temps de mesure assez long. Alors que la période est obtenue immédiatement avec une bonne précision.

bvking:
Peut être quand utilisant une roue codeuse avec plein de fente, j'aurai un meilleur resultat, non?
Quand pensez vous? pour les rebonds..

Je pense que ce serait multiplier le problème.
Il faudrait voir à l'oscillo, s'il y a beaucoup de rebonds.
Eventuellement mettre un filtrage condensateur/réstance, mais là ça sort de mes compétences :confused:

Cordialement
jpbbricole

Oui fdufnews.

J'ai un programme de Tachymetrie.

Mais je ne sais pas comment transformer la periode du signal c'est à dire le nombre de signaux en 1 seconde pour avoir la vitesse de rotation.

Ici, plus on a d'impulsion plus la roue tourne vite et quand il n'y a plus d'impulsion ou moins de une impulsion la roue est stoppée et la frequence sera nulle.

Je ne sais pas comment convertir ce signal en frequence.
Je mets le programme si vous pouvez le corriger, merci d'avance

                  1
période =   --------------
                fréquence

Bonjour,
Je sais bien que f=1/P mais quand j’ai P=0 je peux pas diviser par zero. Comment faire, j’ai essayé avec des if et else, mais j’ai dû faire une erreur. voici mon programme qui fonctionne pas.

motor_l298N_tachymetreafaire.ino (3.66 KB)

Apres modification de mon programme, j'ai toujours des resultats proches de l'aléatoire.

tick= :33076.00
SIGNAL = :1209
vit captée du moteur B: 132
echantillion(indice) : 132
vitesse moyenne du moteur B: 84
vit moy Constrainte à A: 117
tick= :18096.00
SIGNAL = :2210
vit captée du moteur B: 72
echantillion(indice) : 72
vitesse moyenne du moteur B: 70
vit moy Constrainte à A: 106
tick= :36716.00
SIGNAL = :1089
vit captée du moteur B: 146
echantillion(indice) : 146
vitesse moyenne du moteur B: 77
vit moy Constrainte à A: 111
tick= :312.00
SIGNAL = :-2867
vit captée du moteur B: 1
echantillion(indice) : 1
vitesse moyenne du moteur B: 58
vit moy Constrainte à A: 96

Si c'est pas un probleme de programme, pourriez vous me conseiller un moteur+encodeur avc un programme integré pour être sûr que ça fonctionne? ça fait deux semaines que je tourne en rond...

Bonjour bvking

J’ai pas tout compris dans ton programme, je te propose d’essayer mon programme de compte-tours pour voire le résultat, si tu as toujours beaucoup d’instabilité, il faudra filtrer le signal.

Cordialement
jpbbricole

ARDFE_bvkingRPM.ino (1.81 KB)

Bonjour,
Merci Jpb,
Mais je pense avoir trouvé, je vais acheté un encodeur rotatif pour moteur pas à pas. Maintenant faut que je me renseigne sur les caracteristiques techniques.