Moteur CC -Lecture de la vitesse- Reception LoRa: Gestion du temps?

Bonjour,

J'ai un moteur muni d'un codeur incrémental et un module LoRa SX1278. Je souhaite d'une part faire tourner le moteur en lisant sa position angulaire et sa vitesse, d'autre part lire un message LoRa. Chacun de leur côté les deux codes fonctionnent parfaitement.

Pour le moteur seul:

int pinA = 2;   //Codeur incremental broche A
int pinB = 4;   //Codeur incremental broche B
int pin1Moteur = 8;
int pin2Moteur = 9;
int enablePin = 7; // j'utillise un L293D
volatile int pos = 0;          // Position (en nombre de pas) du codeur
volatile float vit = 0;        // Vitesse (en nombre de tour par seconde, 96.8 pas par tour) du codeur
volatile unsigned long t = 0;  // temps "courant" (en microsecondes)


void setup()  {
   Serial.begin(115200);
   Serial.println("Codeur incremental");
   pinMode(pinB, INPUT);
   pinMode(pin1Moteur,OUTPUT);
  pinMode(pin2Moteur, OUTPUT);
  pinMode(enablePin,OUTPUT);
  attachInterrupt(0, front, CHANGE);  // Détection des deux types de fronts
  t = micros();                       // Initialisation du temps "courant"
}

void loop()   {
  digitalWrite(pin1Moteur,LOW);
  digitalWrite(pin2Moteur,HIGH);
  digitalWrite(enablePin,1);
  delay(10);
}

void front()   {
   unsigned long dt = micros() - t;   // Temps écoulé depuis le dernier front
   t += dt;
   int sA = digitalRead(pinA);
   int sB = digitalRead(pinB);
   int apos = pos;                    // Mémorisation de la position précédente
   if (sA == sB)   {
      ++pos;
   }
   else   {
      --pos;
   }
   
   if (dt > 0)   {
      vit = 1e6*(pos-apos)/(dt*96.8);         // Calcul de la vitesse (ici en pas par seconde)
   }
   
   Serial.print(pos);      // Lignes à supprimer après les tests, car elles ralentissent le dispositif
   Serial.print("\t");
   Serial.println(vit);
}

Voilà le genre de résultat que j'obtiens, le compteur a gauche et la vitesse a droite:
5752 5.33
5753 5.87
5754 5.61
5755 5.75
5756 5.70
5757 5.90
5758 5.55
5759 5.80
5760 5.45
5761 5.57
On voit bien que le compteur passe une unique fois sur chacune des positions et la vitesse et stable, 5 tours par seconde c'est cohérent avec ce que j'observe.

Pour le récepteur LoRa seul:

#include <SPI.h>
#include <LoRa.h>

void setup() {
  Serial.begin(9600);

  if (!LoRa.begin(433E6)) {
    Serial.println("Erreur de démarrage LoRa !");
    while (1);
  }
}

void loop() {
  int packetSize = LoRa.parsePacket();

  if (packetSize) {
    // Si des données LoRa sont disponibles
    while (LoRa.available()) {
      // Lire et afficher les données reçues
      Serial.print("Temps reçu: ");
      Serial.println(LoRa.parseInt());
    }
  }
}

J'obtiens bien ce que je veux ici aussi.

Mais quand je les combine, j'obtiens des valeurs de la vitesse délirantes et le compteur aussi semble être gêne car il passe plusieurs fois sur les mêmes positions. Aussi le message LoRa n'est pas lu à chaque interruption. Dans le code je rajoute juste la réception du signal LoRa dans l'interruption. Voici le code:

//Moteur//
int pinA = 2;   // Le port D2 est associé à l'interruption 0
int pinB = 4;
int pin1Moteur = 8;
int pin2Moteur = 9;
int enablePin = 7; 
volatile int pos = 0;  // Position (en nombre de pas) du codeur
volatile float vit = 0;        // Vitesse (en nombre de pas par seconde) du codeur
volatile unsigned long t = 0;  // temps "courant" (en microsecondes)
volatile unsigned long dt = 0;

//Lora//
#include <SPI.h>
#include <LoRa.h>


void setup()  {
  Serial.begin(115200);
  //moteur//
  Serial.println("Codeur incremental");
  pinMode(pinB, INPUT);
  pinMode(pin1Moteur,OUTPUT);
  pinMode(pin2Moteur, OUTPUT);
  pinMode(enablePin,OUTPUT);
  t=micros();
  //Lora//
  if (!LoRa.begin(433E6)) {
    Serial.println("Erreur de démarrage LoRa !");
    while (1);
  }                    // Initialisation du temps "courant"
  attachInterrupt(0, front, CHANGE);  // Détection des deux types de fronts
}

void loop()   {
  digitalWrite(pin1Moteur,HIGH);
  digitalWrite(pin2Moteur,LOW);
  digitalWrite(enablePin,1);
  delay(10); 
}

void front()   {
  //moteur//
  unsigned long dt = micros() - t;   // Temps écoulé depuis le dernier front
  t += dt;
  int sA = digitalRead(pinA);
   int sB = digitalRead(pinB);
   int apos = pos;                    // Mémorisation de la position précédente
   if (sA == sB)   {
      ++pos;
   }
   else   {
      --pos;
   }
   
   if (dt > 0)   {
      vit = 1e6*(pos-apos)/(dt*96.8);         // Calcul de la vitesse (ici en pas par seconde)
   }
  Serial.print("compteur: ");
  Serial.print(pos);     // Ligne à supprimer après les tests, car elle ralenti le dispositif
  Serial.print("  ");
  Serial.print("vitesse: ");
  Serial.println(vit);
  //Lora//
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // Si des données LoRa sont disponibles
    while (LoRa.available()) {
      // Lire et afficher les données reçues
      Serial.print("Temps reçu: ");
      Serial.print(LoRa.parseInt());
      Serial.print("   ");
      Serial.print("RSSI: ");
      Serial.println(LoRa.packetRssi());
    }
  }
  
}

Et voici un exemple de ce que je recois:
compteur: 1434 vitesse: 0.00
compteur: 1433 vitesse: -16.88
compteur: 1434 vitesse: 0.00
compteur: 1433 vitesse: -0.00
compteur: 1434 vitesse: 14.84
compteur: 1435 vitesse: 0.00
compteur: 1436 vitesse: 0.00
compteur: 1437 vitesse: 16.88
Temps reçu: 159055 RSSI: -112
compteur: 1438 vitesse: 0.00
compteur: 1439 vitesse: 14.93

On voit que la même position est lu plusieurs fois, le message LoRa n'est pas lu à chaque interruption, la vitesse est soit nulle soit differentes de ce que je lisais sans le module LoRa. J'ai cru comprendre que le problème venait de la gestion du temps.

Est ce que quelqu'un aurait une solution pour m'aider?

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

Sorry my bad

Pour essayer de résoudre le problème j'ai deja essayer de sortir la lecture du message LoRa de l'interruption en la plaçant dans la boucle loop() et en arrêtant les interruptions lors de la lecture. Comme ceci

void loop()   {
  digitalWrite(pin1Moteur,HIGH);
  digitalWrite(pin2Moteur,LOW);
  digitalWrite(enablePin,1);
  delay(10); 
  noInterrupts();
  //Lora//
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // Si des données LoRa sont disponibles
    while (LoRa.available()) {
      // Lire et afficher les données reçues
      Serial.print("Temps reçu: ");
      Serial.print(LoRa.parseInt());
      Serial.print("   ");
      Serial.print("RSSI: ");
      Serial.println(LoRa.packetRssi());
    }
  }
  interrupts();
}

Cela n'a rien change.

vous avez besoin d'une section critique dans la loop quand vous accédez la variable partagée avec l'interruption.

Ensuite il faut voir si la communication avec votre module LORA ne bloque pas les interruptions trop longtemps, ce qui vous ferait rater des impulsions sur l'encodeur s'il tourne vite

Il faudrait aussi sortir les print de la fonction qui traite les interruptions.
Positionner un drapeau dans l'ISR et gérer l'affichage dans loop()

Si on n'utilise pas .onReceive() la librarie Lora n'utilise pas d'interruption, il me semble.

l'usage de la bibliothèque encoder simplifierait aussi le code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.