Résolution angulaire ou vitesse avec un codeur rotatif sur ESP32

Bonjour,

J'ai un petit projet ou je dois afficher une résolution angulaire (de 0 à 360°) ou une vitesse via un codeur rotatif 2000ppr

J'ai demandé à mon ami chatgpt qui après plusieurs itérations, m'a sorti ce bout de code.
La partie vitesse fonctionne à merveille. J'ai testé jusqu'a 2000RPM et mon ESP32 suit bien.

En revanche la partie résolution c'est la cata. Après plusieurs versions proposées par l'IA, la moins mauvaise est celle-ci. Mon probleme: le MCU crash au bout de quelques secondes si mon codeur tourne. Et je n'arrive pas a trouver pourquoi ca crash

// Broches du codeur rotatif
const int pinCodeurA = 12;
const int pinCodeurB = 14;

// Nombre de pulses par tour
const int pulsesParTour = 2000;

// Variables pour le calcul de la vitesse
volatile int pulses = 0;
volatile unsigned long tempsDernierPulse = 0;
float vitesseRPM = 0.0;

// Variables pour le calcul de la résolution angulaire
volatile float resolution = 0.0;
volatile float lastResolution = -1.0;
volatile bool modeResolution = false;
volatile bool sensRotation = true;
volatile int pulsesSensPrec = 0;

void IRAM_ATTR isrPulse() {
  // Gestion de l'interruption pour les pulses du codeur
  if (sensRotation) {
    pulses++;
  } else {
    pulses--;
  }

  if (modeResolution) {
    // Calcul de la résolution angulaire en mode "resolution"
    float resolutionParPulse = 360.0 / pulsesParTour;
    resolution += resolutionParPulse;
    if (resolution >= 360.0) {
      resolution -= 360.0;
    } else if (resolution < 0.0) {
      resolution += 360.0;
    }
  }
}

void setup() {
  // Initialisation des broches
  pinMode(pinCodeurA, INPUT_PULLUP);
  pinMode(pinCodeurB, INPUT_PULLUP);

  // Attachement de l'interruption aux pulses du codeur
  attachInterrupt(digitalPinToInterrupt(pinCodeurA), isrPulse, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pinCodeurB), isrPulse, CHANGE);

  // Démarrage de la surveillance de la vitesse
  tempsDernierPulse = micros();
  pulses = 0;

  // Configuration de la communication série
  Serial.begin(9600);
}

void loop() {
  // Vérification de la commande série
  if (Serial.available()) {
    String commande = Serial.readStringUntil('\n');
    if (commande == "switch") {
      // Changement de mode
      modeResolution = !modeResolution;

      if (modeResolution) {
        // Passage au mode "résolution"
        Serial.println("Mode de calcul : Resolution angulaire");
      } else {
        // Passage au mode "vitesse"
        Serial.println("Mode de calcul : Vitesse");
      }
    }
  }

  // Calcul de la vitesse toutes les secondes en mode "vitesse"
  if (!modeResolution && micros() - tempsDernierPulse >= 1000000) {
    // Détachement des interruptions pour éviter toute perturbation
    detachInterrupt(digitalPinToInterrupt(pinCodeurA));
    detachInterrupt(digitalPinToInterrupt(pinCodeurB));

    // Calcul de la vitesse en RPM
    vitesseRPM = (float(pulses) / pulsesParTour) * 60.0;

    // Affichage de la vitesse
    Serial.print("Vitesse: ");
    Serial.print(vitesseRPM);
    Serial.println(" RPM");

    // Réinitialisation des variables
    pulses = 0;
    tempsDernierPulse = micros();

    // Réattachement des interruptions
    attachInterrupt(digitalPinToInterrupt(pinCodeurA), isrPulse, CHANGE);
    attachInterrupt(digitalPinToInterrupt(pinCodeurB), isrPulse, CHANGE);
  }

  // Affichage de la résolution angulaire lorsqu'elle change de valeur en mode "resolution"
  if (modeResolution && resolution != lastResolution) {
    Serial.print("Resolution: ");
    Serial.print(resolution);
    Serial.println(" deg");
    lastResolution = resolution;
    delay(100); // Délai pour éviter un affichage trop rapide
  }
}

Et le moniteur serie:

Resolution: 142.20 deg
Resolution: 145.80 deg
Resolution: 153.54 deg
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x4008470c  PS      : 0x00050031  A0      : 0x800f0928  A1      : 0x3ffbf2dc  
A2      : 0x00000040  A3      : 0x00018040  A4      : 0x000637ff  A5      : 0x3ffbf2ac  
A6      : 0x00000000  A7      : 0x3ffbdb94  A8      : 0x00000001  A9      : 0x40087ff2  
A10     : 0x3ffc3c1c  A11     : 0x80000001  A12     : 0x00000001  A13     : 0x3ffbf28c  
A14     : 0x00000000  A15     : 0x00000000  SAR     : 0x00000014  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x800f0934  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  


Backtrace: 0x40084709:0x3ffbf2dc |<-CORRUPTED




ELF file SHA256: 54573742d58cd047

En plus, malgré mes demandes, pour le moment le sketch ne gere pas l'inversion du sens de rotation en mode résolution angulaire. Les pulses sont toujours additionnées et l'IA galère la dessus

ce n'est pas un projet fini...

Je déplace dans le forum principal

lisez les recommandations listées dans "Les bonnes pratiques du Forum Francophone” et donnez plus de détails sur votre montage, carte etc...


sur ESP32 vous pourriez tester GitHub - madhephaestus/ESP32Encoder: A Quadrature and half quadrature PCNT peripheral driven encoder library supporting 8 encoders

Je crois qu'il y a un consensus sur le forum, pour ne pas corriger des programmes générer par chatGPT, surtout lorsque ce programme génère une erreur d'accès.

Par contre si tu as des questions précises ou des essais de code personnel pour changer le sens de rotation par exemple, tu trouvera beaucoup de monde pour t'aider.

par exemple tu note que pulse ne fait que croitre et qu'il n'y a pas de changement de sens.
A quel moment ton code gère l'inversion du sens de rotation et qui permet de passer dans ton code ou tu décrémente la variable pulse ?

Merci je n'étais pas au courant de cette pratique que je comprends tout à fait.
Je suis arrivé à mes fins via l'IA. Pour moi c'était l'occasion de tester l'outil qui peut faire gagner pas mal de temps mais qui n'est pas sans défaut.

je mets le code final pour information meme s'il est relativement éloigné du code initial

const int pinA = 12;
const int pinB = 14;

volatile long encoderPosition = 0;
float degreesPerPulse = 360.0 / 2000.0;
unsigned long lastTime = 0;
float rpm = 0.0;
bool rpmMode = false;

void setup() {
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinA), updateEncoder, CHANGE);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    if (command == "switch") {
      rpmMode = !rpmMode;
      Serial.print("Switched to ");
      Serial.println(rpmMode ? "RPM mode" : "Degrees mode");
    }
  }
  
  if (rpmMode) {
    unsigned long currentTime = millis();
    if (currentTime - lastTime >= 1000) {
      float revs = encoderPosition / 2000.0;
      rpm = abs(revs * 60.0/2);
      encoderPosition = 0;
      lastTime = currentTime;
    }
    //Serial.print("RPM: ");
    Serial.println(rpm);
  } else {
    float degrees = encoderPosition * degreesPerPulse/2
    ;
    degrees = fmod(degrees, 360.0);
    if (degrees < 0) {
      degrees += 360.0;
    }
    //Serial.print("Degrees: ");
    Serial.println(degrees);
  }

  delay(100);
}

void updateEncoder() {
  if (digitalRead(pinA) == digitalRead(pinB)) {
    encoderPosition++;
  } else {
    encoderPosition--;
  }
}

dans l'absolu cette partie

devrait nécessiter une section critique car vous lisez encoderPosition qui peut être en même temps modifié par l'interruption

dites le à chatGPT...

Oui, il ferra d'ailleurs gagner d'autant plus de temps que tu connais la programmation.
Le seul soucis que je vois à cette pratique, c'est que tu n'a pas compris ce qui te bloquais, donc tu ne sera pas capable de modifier ou ajuster ton code, sans l'aide de chatGPT.
Mais si c'est ce que tu cherchais, là est le principal.

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