Récupération données MCC avec Codeur incrémental

Bonjour, dans le cadre d'un projet étuidant je dois récupérer les données d'un moteur. Pour cela j'ai donc un code qui me permet d'obtenir les "ticks" de la codeuse en fonction de si le moteur tourne à droite ou à gauche et le temps (en microseconde) entre deux ticks. Cependant quand je rajoute une ligne me permettant d'obtenir la position angulaire du moteur, il apparaît une sorte de conflit et je n'obtiens plus comme avant les ticks exact du au mouvement du moteur. A partir d'un moment x, le programme me donne des valeurs incohérentes. Voici le programme :

En attente de votre aide éventuelle, je vous souhaite une bonne journée.

hello
pourquoi une copie d'écran.
dans l'ide ARDUINO, tu fais:
dans les menus, "outils", "formater". cela va mettre ton code proprement.
ensuite tu sélectionne ton code et tu fais "copier".
dans la fenetre de ton post sur le forum, tu cliques sur l'icone "</>"
apparaitra : <..........................> et ton curseur sur les points, tu fais "coller"

outre le plaisir d'avoir un code agreable à lire, nous pourrons alors copier ton code, le tester chez nous et te dire ce que nous en pensons

perso, j'ai voulu le copier et comme ce n'est as possible et que je n'ai pas l'intention de le retaper ..........................

int pinA = 2;   // Le port D2 est associé à l'interruption 0
int pinB = 3;
volatile int pos = 0;  // Position (en nombre de pas) du codeur
volatile unsigned long t = 0;  // temps courant en (micro secondes)

void setup()  {
  Serial.begin(115200);
  Serial.println("Codeur incremental");
  pinMode(pinB, INPUT);
  attachInterrupt(0, front, FALLING);  // Détection des fronts descendants
  t = micros();  // initialisation du temps courant
}

void loop()   {
  delay(10);
}

void front()   {
  unsigned long dt = micros() - t;  // temps écoulé depuis le dernier front
  t = t + dt;
  int s = digitalRead(pinB);
  if (s == LOW)   {
    ++pos;
  }
  else   {
    --pos;
  }
  Serial.println(pos);   // Ligne à supprimer après les tests, car elle ralenti le dispositif
  Serial.print("\t");
  Serial.println(float(pos) / 334, 5); // Ligne censé me donner la position angulaire en fonction des ticks de la codeuse
  Serial.println(dt);
}

Voici le code plus "propre" que vous attendiez.

c'est quoi 334? si c'est le nombre d'impulsions par tour, tu calcules un nombre de tours.

pourquoi enregistrer le temps? tu ne t'en sers pas ensuite?

ton prg fait le calcul et l'affichage à chaque interruption!!!
il faut le faire dans la loop

334 correspond approximativement aux nombres d'impulsions pour 1 rad.

Le temps me sera utile car ensuite ayant la position et le temps, je pourrai faire un taux d'accroissement et obtenir la vitesse, et par la même occasion obtenir les paramètres de mon moteur en traçant la vitesse de rotation du moteur en fonction du temps

suis pas sur d'avoir tout compris
regarde ce code

int pinA = 2;   // Le port D2 est associé à l'interruption 0
int pinB = 3;
volatile long pos = 0;  // Position (en nombre de pas) du codeur
volatile unsigned long t = 0;  // temps courant en (micro secondes)
volatile unsigned long dt = 0;
//2098 tic/tr
void setup()  {
  Serial.begin(115200);
  Serial.println("Codeur incremental");
  pinMode(pinB, INPUT);
  attachInterrupt(0, front, FALLING);  // Détection des fronts descendants
  t = micros();  // initialisation du temps courant
}

void loop()   {
  // Serial.print(dt); //Serial.print("\t");

  long tic_seconde = (1000000 / dt); //*60;//
  //Serial.print(tic_seconde);//Serial.print("\t");

  long tr_seconde = ((1000000 / dt) / 2098);
  //Serial.print(tr_seconde);//Serial.print("\t");

  long tr_minute = ((1000000 / dt) / 2098) * 60;
  Serial.println(tr_minute);
}

void front()
{
  dt = micros() - t;  // temps écoulé depuis le dernier front
  t = micros();
  if (digitalRead(pinB) == LOW)   {
    ++pos;
  }
  else   {
    --pos;
  }
}

Je fais le pari que dans les "print" il y a des masquages d'interruptions qui vous font perdre des ticks de votre roue codeuse.

hello jp38
oui bien sur, les print ne sont là que pour le debug et la démonstration

Maintenant que tu t'est donné la peine de donner un programme lisible, voici quelques remarques:

Si le codeur fait de l'ordre de 1000 impulsions par tour, il faut noter que si il fait 10 tours par seconde, il faut que la routine d'interruption dure moins d'100µs. Supposons le cas contraire et que a routine dure 160µs. Il y aura plus d'inter que ce que peut gérer le microcontrôleur, et il passera sa vie dans la routine t n'affichera plus rien. Rallonger la routine d'inter permettra de mesurer la routine et plus le codeur. Il est probable que la ligne

Serial.println(float(pos) / 334, 5);

dépende de l'affichage. Par exemple au début le temps est court puis plus on prend du temps, plus il y a de chiffres et plus la routine est longue...

Il est essentiel de respecter un temps du programme d'inter inférieur à la période de répétitions des inters, sauf si le code est écrit en conséquence. Il faut donc estimer quelle sont ces deux grandeurs. Pour estimer le temps de la routine, on peut y rajouter un compteur genre:

if (mesureDuTemps++ == 10000) Serial.print(millis());

Et on se débrouille pour lui demander trop d'interruptions.
Une autre solution consiste à afficher dans loop les secondes avec un temps d'attente de _delay_ms(1000); (temps fait par boucle). Et si on passe la moitié du temps dans l'inter, loop affichera un temps double.

de mémoire dure 1/8ms


Dans le programme de @dfgh, la ligne

peut être interrompue au milieu du calcul et la valeur de dt peut changer pendant la division, ce qui donne un résultat faux. Pour éviter cela, il faut quand on fait un calcul avec un nombre de 2 octets et plus désactiver les interruptions. Par exemple:

  noInterrupts();
  long tic_seconde = (1000000 / dt); //*60;//
  noInterrupts();

Il faut avoir les valeurs des temps des mesures. Le temps d'un tic est stockée dans une variable qui permet les mesures jusqu'à 52 jours. Est-ce utile? Quel est le temps maxi à mesurer? Sur combien de bits sont utiles? Si la réponse était 8, alors

long tic_seconde = (1000000 / dt); //*60;//`
[/quote]
serait correct

Cela voudrait dire qu'il y aurait incompatibilité avec l'horloge interne et les bibliothèques utilisant les interruptions. J'ai de gros doutes.

Pour le savoir on peut éviter les "print" et voir si ça change quelque chose. En tous cas, sur le principe, pour moi il est évident que si dans une bibliothèque l'auteur a masqué les interruptions pendant un temps supérieur à la période des ticks de la roue codeuse, on va perdre des incréments de position.