Mesure de vitesse d'un chariot

Bonjour à tous,
Je voudrais enregistrer les variations de vitesse d’un chariot entrainé par un stepper lors d’un déplacement, c’est à dire avec la phase d’accélération, la vitesse atteinte et la phase de freinage. Le problème est que le déplacement complet dure environ 100 ms. Je dispose d’une roue codeuse. J’ai essayé avec un accélérometre mais le signal est brouillé par les steps du moteur. Je pensais utiliser les timers du micro et les int avec un datalogger mais je ne suis pas sûr que l’arduino Uno soit assez rapide pour tout gérer. Des idées ?
Merci
Fred

pas simple sur 100ms

J’imagine que sur ce temps il se déplace en ligne droite sur un rail ?

Même un capteur de distance laser genre tiny Lidar ne délivre que du 60Hz donc vous n’aurez que 6 mesures sur 100ms, pas assez pour tracer la distance en fonction du temps et donc déduire les vitesses / accélérations

Qui pilote le stepper ? est-ce que ça ne peut pas être instrumenté à ce niveau ? (interruption sur les pas ou micros-pas à condition qu’il n’y ait pas de glissement)

Bonjour J-M-L,
Merci pour ta réponse
J’ai essayé en enregistrant la largeur des steps du moteur au niveau de la commande du moteur et en passant par une fft mais sur un signal rectangulaire, bonjour les harmoniques. j’arrive à voir les rampes d’accélérations et de freinage mais le chariot est entrainé via une courroie et je voudrai être certain que la courroie ne se déforme pas.

Mettre un encodeur absolu hall genre as5047 en axial et faire du log
Il existe de encodeurs montés sur des pcb pour être fixés directement sur des pap à la norme NEMA

exemple

Qu’appelez vous une roue codeuse ? Une roue entrainée par le chariot avec un codeur incrémental monté dessus ? Si vous avez ça, vous reliez l’un des signaux de ce codeur sur une entrée logique, sur laquelle vous déclenchez une interruption. A chaque passage dans l’ISR, vous empilez dans un buffer la valeur de la fonction micros(). Quand le mouvement est fini, vous dépilez le buffer et vous avez une loi temps fonction de la distance. Il suffit de la lire dans l’autre sens pour avoir les vitesses et accélérations.

hello
as tu pensé à un analysreur logique de type SAELAE?

@Artouste et joPe38
C’est ce que je pensais faire avec ma roue codeuse mais je ne suis pas sûr que l’arduino soit assez rapide pour gérer la lecture de la roue et le logging.
@dfgh
je saisis mal l’utilité d 'un a.l. dans ce cas

Vous prenez le nombre de pulses par tour, multipliez par le nombre de tours par seconde, ça vous donne le nombre d’interruptions par seconde. Pour lire micros() et l’empiler dans un buffer, vous n’avez pas besoin de beaucoup de temps. Par exemple si ce nombre est inférieur à 20 kHz, ça devrait passer les doigts dans le nez. Sinon, prenez plus costaud qu’un UNO.

Il faut que la roue codeuse tourne très vite / ait un grand nombre de pôles
Quelle est la vitesse du chariot et/ou la distance parcourue pendant ces 100ms ?

je suppose que ton moteur pas à pas est piloté pa un driver.
ce driver doit reçevoir un signal carré de frequence variable
à l’accel, ta frequence part de zero à xxx,
en vitesse établie, la fréquence est fixe xxx,
à la décélération, ta fréquence diminue de xxx à 0.

un analyseur logique te permet de voir le signal sur toute sa durée et tu visualises aussi les µsecondes

tu peux donc calculer tes vitesses
une accel à titre d’eemple

et une decel

Soit le moteur loupe des pas, soit il suit bêtement ce que lui dit le logiciel. Si on est dans le second cas, il suffit de regarder ce qu’envoie le logiciel. On peut faire alors une erreur d’au plus un pas.
Si on peut trouver ce que fait le logiciel et on a une réponse directe. Sinon il suffit de demander le même mouvement mais 1000 fois plus lentement et un Serial.println(micros()); ou un table[step++]=micros(); bien placé donnera les infos

Si la courroie peut se déformer, il faut oublier tous les encodeurs sur l’axe moteur. Mais si la courroie se déforme sous l’effort, la déformation risque d’être voisine à vitesse de croisière ou en statique. Pour avoir une idée sur la déformation de la courroie c’est de bloquer le moteur et de tirer sur le chariot

Vous ne nous avez toujours pas dit ce que vous appelez “une roue codeuse”, où elle se situe mécaniquement (c’est une roue du chariot ou sur l’axe moteur), ni combien de pulses par tour elle envoie, ni la vitesse à laquelle elle tourne. Et avec ça vous voudriez qu’on vous propose une solution de micro-informatique pour contrôler votre transmission mécanique…

@ JiPe38
Du calme ! :wink: … mais merci quand même. Je ne fais pas que cela (Je suis grand-père!).
Je détaille.Une roue codeuse, bref un encodeur optique qui délivre 600 pulses par tour sur un diamètre de 2,4 cm et qui se déplace jusqu’ à 2m/s.
A 2m/s , j’ai 83 us pour faire une acquisition (sauf erreur de calcul).
Actuellement j’ai fait un essai en branchant mon encodeur sur la pin 2 (int 0) pour générer une interruption à chaque front montant. Et sur cette interruption, je copie micros() dans un fichier csv via un shield datalogger.
Théoriquement, j’ai le temps mis entre 2 pulses de l’encodeur et la distance correspondante entre ces deux pulses. Donc je devrais pouvoir sortir la vitesse. Mais dans mon fichier, j’arrive à avoir des durées négatives entre 2 pulses consécutifs. t2<t1. alors que micros() ne fait qu’augmenter donc t2-t1 devrait toujours être positif. (sauf quand il est remis à 0 toutes les 70 min). Avoir des durées nulles: OK y a un bug dans mon programme mais négatives, je pige pas.
je communique avec la datalogger via SPI. je ne connais pas les caractéristiques exactes du SPI mais je pensais que ça passe. Pas sûr !
Je vais essayer en bufferisant les données et en les envoyant par paquets.
Quelle la taille maxi du buffer?

voilà où j’en suis …

Fred

voilà où j’en suis !

Merci

Lorsque les encodeurs sont donnés pour 600 points par tour, avec deux signaux en quadrature, cela signifie que si on ne prend qu’un des deux signaux il fait 150 cycles par tour. Donc si vous ramenez ça sur une entrée et déclenchez l’interruption sur front montant, vous devriez avoir 150 interruptions par tour et, possiblement suivant comment vous avez fait vos calculs, 320 us entre deux interruptions, soit un peu plus de 3 kHz de fréquence. Mais si effectivement l’encodeur a une résolution de 2400 points par tour, cela fait bien 600 interruptions par tour et, je vous fais confiance pour le calcul, 83 us entre deux interruptions. A 83 us soit 12 kHz, sur un UNO, il ne faut pas trainer dans l’ISR et, en particulier ne pas vouloir programmer une écriture sur carte SD. La seule possibilité pour vous en tirer est de remplir un buffer (un tableau en mémoire) avec vos valeurs de micros(), et si j’ai bien suivi votre tableau contiendra 1200 valeurs. Une fois le mouvement terminé, vous pourrez tranquillement transférer ce tableau vers un fichier sur carte SD, même pourquoi pas en “human readable” en ASCII. Cela si votre manip est de type “expérimentale”. Si vous voulez faire du suivi en permanence, il faut prévoir d’avoir deux tableaux : un en cours de remplissage par l’ISR, un autre en cours de transfert (par la boucle loop de fond) vers la carte SD. Vous alternez en séquence :
1 - Remplissage tableau A par l’ISR et vidage tableau B vers la carte SD par la tache de fond.
2 - Remplissage tableau B par l’ISR et vidage tableau A vers la carte SD par la tache de fond.
Cela dans l’hypothèse où vos mouvements s’enchainent rapidement et que vous n’avez pas le temps de faire le remplissage / le vidage l’un après l’autre.
Mais dans tous les cas, même si vous avez 320 us entre deux interruptions, vous n’avez pas le temps d’aller écrire sur le carte SD à chaque lecture de micros()

D’autre part je ne connais pas suffisamment ces cartes Arduino pour en être sur, mais je doute que la valeur lue sur micros() soit précise à la us. Je ne serais pas surpris que l’on lise des multiples, par exemple 8 us. Attention aussi à ne pas faire d’entrées sorties, avec des bibliothèques (et la carte SD en est une) qui masque les interruptions pendant des séquences critiques, ce qui pourrait vous faire louper des pulses et vous faire croire que la courroie est entrain de casser !

tout à fait → c’est 4µs

Effectivement, Je vais essayer en bufferisant et en faisant un vidage à la fin de du déplacement. L’idée d’utiliser deux tableaux en remplissant avec l’ISR et en vidant avec la tâche de fond les deux tableaux en alternance, est astucieuse. Quand à la précision , ce n’est pas ce qui m’importe le plus, je cherche des mesures cohérentes. et avoir des incréments négatifs, sur un compteur qui ne peut qu’augmenter, je ne vois pas comment c’est possible. Dans le pire des cas , je relève deux valeurs identiques mais une valeur t1 et ensuite une deuxième valeur t2 plus petite, je ne comprends. Même si une interruption passe au milieu, j’aurais au pire deux valeurs identiques. Par contre, il est possible que l’écriture sur la carte SD, je vais vérifier, masque les ISR. Si la courroie casse, je crois que je le verrai de visu ;-). Merci pour les idées et l’aide.
Fred

la carte SD utilise un buffer de 512 octets, si vous ne fermez pas le fichier ni ne faites de flush() et que vous n’occupez pas les 512 octets il n’y a pas d’écriture réelle sur la carte, tout reste en mémoire

faudrait voir votre code de

1 - Remplissage tableau A par l’ISR et vidage tableau B vers la carte SD par la tache de fond.
2 - Remplissage tableau B par l’ISR et vidage tableau A vers la carte SD par la tache de fond.

pour comprendre vos nombres négatifs

Attention aussi aux vibrations. Sur un codeur, une vibration angulaire de l’axe peut envoyer une rafale de changements d’état alors que la position reste dans le voisinage d’une position angulaire donnée. Surtout sensible aux basses vitesses ou près de la position d’arrêt. Sur 100 ms le temps total est 100 000 us. Si vous divisez par quatre (shift deux positions à droite) vous descendez à 25 000, ce qui se code sur un entier 16 bits et vous prendra moins de place en mémoire. Et vu ce qui est écrit plus haut, les deux derniers bits doivent être non significatifs. Pensez que l’écriture sur la carte SD, bien que bufferisé, va utiliser des interruptions et peut être des masquages d’interruptions et que si vous êtes entrain de faire vos acquisitions en meme temps, ça va perturber. On ne peut jamais savoir, quand on utilise une bibliothèque, quelle est la durée des masquages d’interruptions qui y ont été programmés.

4µs c’est la résolution, ce n’est pas la précision. Sachant qu’il y a une interruption système qui dure 6µs et que pendant ce temps les interruptions sont reportées, la mesure n’est pas extraordinaire.

Pour faire une mesure un peu correcte dans ce cas là, la solution que je conseille est d’utiliser un timer 16 bits pour lequel on peut avoir une résolution entre 62,5ns et 64µs et de faire:

  • désactivation de l’horloge interne du timer 0
  • facultativement remettre le timer à 0 en début
  • sur interruption, lire la valeur du compteur et la mettre dans un tableau
    C’est bien gentil de vouloir la mettre directement dans le buffer de la SD, mais il faut garantir que la valeur soit bien enregistrée dans le buffer avant que la suivante n’arrive. Il vaut mieux mettre tout dans un tableau et faire un transfert après soit sur une SD soit sur le moniteur série, pour ne pas que l’interruption de l’écriture ne vienne fausser les mesures.
    Si le timer déborde, cela est sans conséquence vu qu’il suffit d’ajouter 0xFFFF pour toutes les valeurs qui suivent un temps fortement négatif. Cela peut donc se faire avec un compteur 8 bits.

Avec une ISR il y a une erreur de mesure car elle ne peut démarrer que lorsqu’une instruction est finie. Ce qui peut faire 0 à 2 cycles d’horloge en plus.

Cette méthode de la lecture directe d’un timer est utilisée pour avoir la durée d’une instruction exacte.