problème vitesse de lecture encodeur

Bonjour,
dans le but de piloter les mouvements altitude et azimut d'un télescope:
j'utilise un arduino nano qui détecte les mouvements sur deux encodeurs rotatifs 600 pas/tour
il envoie les informations par bluetooth à un RPI
j'utilise les pins 2 et 3 pour un des fils (vert) des encodeurs
c'est la bibliothèque "encoder.h" qui gère les interruptions
tout se passe bien si je bouge gentiment l'engin, dès que j'accélère un poil, les informations sont fausses
j'ai l'impression que le nano ne suit pas
en quelques secondes, il peut avoir + de 15000 opérations à gérer
plusieurs idées:
--utiliser un nano par encodeur et dédiés que pour cette tache
--quel autre arduino choisir? le nano n'a que 2 interruptions et l'auteur de la biblio précise que le résultat est meilleur lorsque les deux fils sont sur interruptions
il faudrait donc 4 interruptions
--sinon, j'y pense tout d'un coup, utiliser millis() pour que, toutes les 0.x secondes par ex, le programme lise l'état de l'encodeur
le code actuel de la partie encodeur est fort simple

#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>
Encoder enc_az(3, 11);
Encoder enc_al(2,9);
long al_old  = 0;
long az_old  = 0;
long al_new =0;
long az_new =0;
void loop()      {
  al_new = enc_al.read();
  if (al_new != al_old) {
    al_old = al_new;
bluetooth.println("encodeur altitude " + String(al_new));
    Serial.print("al");
    Serial.println(al_new);
    exit;}
//***********    
  az_new = enc_az.read();
  if (az_new != az_old) {
    az_old = az_new;
bluetooth.println("encodeur azimut " + String(az_new));
    Serial.print("az");
    Serial.println(az_new);
    exit;}

merci de m'avoir lu

Bonjour,
C'est quoi ces exit dans tous les if?
Si tu veux un programme réactif, il faut être un peu moins verbeux et limiter les print vers la console et vers le bluetooth.
Ce serait bien aussi d'avoir le programme complet.
Au passage, ton interface bluetooth doit sans doute utiliser newSoftSerial. Cette librairie désactive les interruptions de temps en temps cela peut donc nuire aux performances.

gerard33:
Bonjour,
dans le but de piloter les mouvements altitude et azimut d'un télescope:
j'utilise un arduino nano qui détecte les mouvements sur deux encodeurs rotatifs 600 pas/tour
il envoie les informations par bluetooth à un RPI
j'utilise les pins 2 et 3 pour un des fils (vert) des encodeurs
c'est la bibliothèque "encoder.h" qui gère les interruptions
tout se passe bien si je bouge gentiment l'engin, dès que j'accélère un poil, les informations sont fausses
j'ai l'impression que le nano ne suit pas
en quelques secondes, il peut avoir + de 15000 opérations à gérer
plusieurs idées:
--utiliser un nano par encodeur et dédiés que pour cette tache
--quel autre arduino choisir? le nano n'a que 2 interruptions et l'auteur de la biblio précise que le résultat est meilleur lorsque les deux fils sont sur interruptions
il faudrait donc 4 interruptions
--sinon, j'y pense tout d'un coup, utiliser millis() pour que, toutes les 0.x secondes par ex, le programme lise l'état de l'encodeur
le code actuel de la partie encodeur est fort simple

#define ENCODER_OPTIMIZE_INTERRUPTS

#include <Encoder.h>





Encoder enc_az(3, 11);
Encoder enc_al(2,9);





long al_old  = 0;
long az_old  = 0;
long al_new =0;
long az_new =0;





void loop()      {
 al_new = enc_al.read();
 if (al_new != al_old) {
   al_old = al_new;
bluetooth.println("encodeur altitude " + String(al_new));
   Serial.print("al");
   Serial.println(al_new);
   exit;}
//***********    
 az_new = enc_az.read();
 if (az_new != az_old) {
   az_old = az_new;
bluetooth.println("encodeur azimut " + String(az_new));
   Serial.print("az");
   Serial.println(az_new);
   exit;}



merci de m'avoir lu

Bonjour
Oui , tu a tout interet à n'envoyer par BT que si al OU az ont changés de valeur dans un delai de x ms (délai acceptable pour toi)

fdufnews:
Bonjour,
C'est quoi ces exit dans tous les if?
Si tu veux un programme réactif, il faut être un peu moins verbeux et limiter les print vers la console et vers le bluetooth.
Ce serait bien aussi d'avoir le programme complet.
Au passage, ton interface bluetooth doit sans doute utiliser newSoftSerial. Cette librairie désactive les interruptions de temps en temps cela peut donc nuire aux performances.

tu as raison, il y a du ménage à faire
pour les print, c'est provisoire, juste pour voir si cela fonctionne, après je vire tout
cela fait 2 ans que j'utilise ça, et cela demande d'y revenir un peu (mais ça fonctionne :slight_smile: )
la librairie c'est "SoftwareSerial.h", je ne connais pas celle que tu cites
pour le code, la limitation des 9000 caractères du forum me jette

Artouste:
Bonjour
Oui , tu a tout interet à n'envoyer par BT que si al OU az ont changés de valeur dans un delai de x ms (délai acceptable pour toi)

oui, je vais essayer ça
sinon, je ne connais pas les nouveaux arduinos, des conseils ?

Ce genre de bibliothèque (encoder.h) qui utilise des interruptions sur les entrées du codeur est incompatible avec tout programme qui bloque les interruptions. Je mettrais volontiers en cause la bibliothèque Bluetooth pour bloquer les entrées.

Je vous suggère d'utiliser un ESP32 qui a des compteurs sur entrée externe, chaque compteur pouvant être configuré avec une entrée "pulse" et une entrée "dir". La matrice de connexion du micro permet, avec seulement deux Pin reliées aux deux voies de l'encodeur, de rediriger chaque signal vers le "pulse" d'un compteur et le "dir" de l'autre. Avec ça vous pouvez compter jusqu'à des mégahertz sans jamais perdre de position. Et comme c'est du câblé, vous pouvez en parallèle faire tourner une biblio qui utilise des interruptions, qui les masque, etc... pas d'interférence.

JiPe38:
Ce genre de bibliothèque (encoder.h) qui utilise des interruptions sur les entrées du codeur est incompatible avec tout programme qui bloque les interruptions. Je mettrais volontiers en cause la bibliothèque Bluetooth pour bloquer les entrées.

Je vous suggère d'utiliser un ESP32 qui a des compteurs sur entrée externe, chaque compteur pouvant être configuré avec une entrée "pulse" et une entrée "dir". La matrice de connexion du micro permet, avec seulement deux Pin reliées aux deux voies de l'encodeur, de rediriger chaque signal vers le "pulse" d'un compteur et le "dir" de l'autre. Avec ça vous pouvez compter jusqu'à des mégahertz sans jamais perdre de position. Et comme c'est du câblé, vous pouvez en parallèle faire tourner une biblio qui utilise des interruptions, qui les masque, etc... pas d'interférence.

je vais essayer de limiter au maximum les appels au bluetooth
pour l'ESP32, ça fait un moment que j'ai envie d'essayer, ce qui me bloquait était l'absence de 5V mais bon j'ai du 12 dans le boitier: je mettrai un petit transfo
merci pour ces conseils :slight_smile:

Ou une autre solution, que j'ai utilisée il y a bien longtemps. A partir des deux signaux d'encodeur, dans une petite machine à état synchrone sur l'horloge du micro (plusieurs Mhz), réalisée avec un PAL, sortir un signal "count up" et un signal "count down", qui sont appliqués à deux compteurs distincts. En faisant la différence entre les deux compteurs, on a la position. A l'époque, je l'ai fait avec des compteurs 16 bits. Je pense que cela aurait pu fonctionner avec des compteurs 8 bits, en utilisant les interruptions sur le débordement de ces compteurs pour générer par logiciel les bits de poids forts.

JiPe38:
Ou une autre solution, que j'ai utilisée il y a bien longtemps. A partir des deux signaux d'encodeur, dans une petite machine à état synchrone sur l'horloge du micro (plusieurs Mhz), réalisée avec un PAL, sortir un signal "count up" et un signal "count down", qui sont appliqués à deux compteurs distincts. En faisant la différence entre les deux compteurs, on a la position. A l'époque, je l'ai fait avec des compteurs 16 bits. Je pense que cela aurait pu fonctionner avec des compteurs 8 bits, en utilisant les interruptions sur le débordement de ces compteurs pour générer par logiciel les bits de poids forts.

j'ai pas vraiment le niveau pour faire ça :o
je viens de commander un ESP32
ce qui m'intéresse aussi c'est son bluetooth intégré dans la mesure où les éléments sont en mouvements distincts ce qui interdit le "câblage filaire"
j'ai des nodemcu ESP 8266, cela marcherait peut-être, le processeur est plus rapide que le nano.....

Tu as parlé du problème, mais pas de ton besoin.
Apparement tes capteurs sont capables de t'envoyer beaucoup d'infos, mais toi, finalement il te faut quel débit d'information ? Tu veux tout garder ? Ou faire du polling (= interroger de temps en temps et prendre la valeur à ce moment là) te suffit ? Dans ce dernier cas, il te faut combien de valeurs par seconde ( et par capteur ) ?

Parce que bien sûr les solutions dépendent énormément de ton besoin.
Sortir l'artillerie lourdes des interruptions ou faire une boucle toute bête avec un delay() ?

He bien s'il a des encodeurs 600 pas/tour, en supposant un pas = 1/4 cycle, et qu'il tourne à 25 tours / seconde, ça fait du 15 000 informations par seconde à prendre. Par polling, on n'y songe même pas, et par interruptions cela n'est pas étonnant que le micro se mette à genoux. Si "pas" signifie cycle, alors multiplier ces chiffres par quatre.

biggil:
Tu as parlé du problème, mais pas de ton besoin.

C'est vrai
Un relevé tous les 1/10s suffit
Par contre, l'arduino ayant d'autres tâches, "delay" ne Va-t-il pas faire des ralentissements ?

JiPe38:
He bien s'il a des encodeurs 600 pas/tour, en supposant un pas = 1/4 cycle, et qu'il tourne à 25 tours / seconde, ça fait du 15 000 informations par seconde à prendre.

Oui, je vais prendre l'option un test par 1/10s
En attendant de recevoir l'esp32 commandé tout à l'heure

gerard33:
Oui, je vais prendre l'option un test par 1/10s
En attendant de recevoir l'esp32 commandé tout à l'heure

Un relevé tous les 1/10s pour un codeur incrémental ??? Votre codeur tourne à quelle vitesse, en tours/s ou tour/mn si vous préférez ?

JiPe38:
Un relevé tous les 1/10s pour un codeur incrémental ??? Votre codeur tourne à quelle vitesse, en tours/s ou tour/mn si vous préférez ?

Et bien, sa roulette (D=30mm) va parcourir +de 1 ml en 2 ou 3s soit 600 pas*30 et quelques
Disons 20000 à la louche (multiplié *4 d'après ce que j'ai compris)
En tour/s ça doit faire.... beaucoup
Là je suis sur mon téléphone et je n'ai pas les chiffres exacts
Lundi je pourrai répondre plus précisément
Merci en tout cas de vous intéresser à mes soucis

J'ai une petite expérience avec les encodeurs quadratiques sur la carte Arduino DUE car ce microcontrôleur a 2 hardware décodeurs quadratiques. Les pulses PHA/PHB ne sont pas comptabilisés par interruptions mais directement au fil de l'eau par les timers sur lesquels ils sont raccordés. Il peut y avoir en plus une broche INDEX qui présente un front haut après chaque tour complet ce qui remet à zéro les compteurs de PHA/PHB. Pour info, en simulant un encodeur quadratique à partir des sorties d'un autre timer, j'arrive à comptabiliser, sans rien perdre, jusqu'à 42 millions d'edges ( = un front montnant ou un front descendant) par seconde.

Donc si le nombre de tours par secondes * le nombre de pulses par tour est très important, il faut nécessairement passer à un uc qui sache traiter en hardware la réception de PHA/PHB faute de quoi des fronts sont perdus, donc la précision diminue.

ard_newbie:
J'ai une petite expérience avec les encodeurs quadratiques sur la carte Arduino DUE car ce microcontrôleur a 2 hardware décodeurs quadratiques. Les pulses PHA/PHB ne sont pas comptabilisés par interruptions mais directement au fil de l'eau par les timers sur lesquels ils sont raccordés. Il peut y avoir en plus une broche INDEX qui présente un front haut après chaque tour complet ce qui remet à zéro les compteurs de PHA/PHB. Pour info, en simulant un encodeur quadratique à partir des sorties d'un autre timer, j'arrive à comptabiliser, sans rien perdre, jusqu'à 42 millions d'edges ( = un front montnant ou un front descendant) par seconde.

Très intéressant aussi
Je ne connais pas ce DUE, il a l'air d'être beaucoup plus puissant que le nano
Je vais essayer les ESP32 commandés hier et si cela ne va pas, je prendrai ce DUE
Les autres me serviront toujours
Merci

gerard33:
Très intéressant aussi
Je ne connais pas ce DUE, il a l'air d'être beaucoup plus puissant que le nano
Je vais essayer les ESP32 commandés hier et si cela ne va pas, je prendrai ce DUE
Les autres me serviront toujours
Merci

bonjour
avec l'esp32 il y a qq library counter dediée
celle ci a une tres faible empreinte
tu a commandé quoi exactement comme "esp32" ?

Et bien, sa roulette (D=30mm) va parcourir +de 1 ml en 2 ou 3s soit 600 pas*30 et quelques
Disons 20000 à la louche (multiplié *4 d'après ce que j'ai compris)
En tour/s ça doit faire.... beaucoup

avertissement: ce qui suit, est "sauf erreur de ma part"

tu veux dire 1 metre linéaire pour 2 secondes? soit 30 metres linéaires par minute soit 3000cm/minute
avec une circonférence de roue de ~10cm cela nous donne 3000/10=300tr/minute
600pions/tr 300=180000pions/minute en simple comptage
si tu comptes les 4 fronts 180 000
4 = 720 000pions/minute ou 720 000 pions/300cm.
ou en mm: 3000 et 720 000 pions
cela donne une résolution par pion de 3000/720 000 = 0.004mm/pion soit 4µ/pion
une fréquence d'interruptions à 12000Hz soit une interruption toutes les 83 µsecondes
s'il te faut une telle précision, tu as besoin d'un µ qui cavale vite.
tu as vraiment besoin d'une telle résolution ?

s'il te faut une telle précision, tu as besoin d'un µ qui cavale vite.

si le microncontrolleur peut gérer l'encodeur sans interruptions , ou du moins avec des interruptions espacées (débordement de compteur) sa vitesse est moins contraignante.

L'ESP32 contient bloc de 8 compteurs 16 bits (bloc PCNT) dont la progression peut dépendre directement des signaux en quadrature, seuls des évènemenats particuliers tels que débordements, franchissement de seuil.. donnent lieu à un traitement par interruption.
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html