Multiple interrupt to get hall cell and fcem problem

Actually i don't understand why my timer are variable and why i don't get a constant phase shift, can somoene help me with my code thanks you very much.
CODE :

// Déclaration des broches pour les signaux
const int Phase1 = 2; // Utilisation de la broche P1_Pin
const int Hall_PulsePin1 = 3; // Utilisation de la broche H1_Pin 

// Période de la phase
unsigned long period_Phase_1 = 0;
unsigned long Period_Hall_1 = 0;

// Temps de début des impulsions
volatile unsigned long startTime_Phase_1 = 0;
volatile unsigned long stopTime_Phase_1 = 0;
volatile unsigned long startTime_Hall_1 = 0;
volatile unsigned long stopTime_Hall_1 = 0;

// Détection des impulsions
volatile bool phase1_detected = false;
volatile bool hall1_detected = false;

// Variables pour la détection des valeurs minimales et maximales
float minValue = 0;
float maxValue = 0;

// Détection moyenne 
float sumAngles = 0; // Somme des angles
int angleCount = 0;   // Compteur d'angles

void setup() {
  // Configuration des broches en entrée
  pinMode(Phase1, INPUT);
  pinMode(Hall_PulsePin1, INPUT);

  // Démarrage de la communication série
  Serial.begin(9600);

  // Attachement des interruptions pour détecter les fronts montants
  attachInterrupt(digitalPinToInterrupt(Phase1), countPulse_Phase1, RISING);
  attachInterrupt(digitalPinToInterrupt(Hall_PulsePin1), countPulse_Hall1, RISING);
}

void loop(){
  // Ne rien mettre ici
}

void countPulse_Phase1() {
  if (!phase1_detected) {
    // Première détection de Phase1, démarrage des deux timers
    startTime_Phase_1 = micros();
    startTime_Hall_1 = micros();
    phase1_detected = true;
  } else {
    // Détection suivante de Phase1, calcul de la période entre les fronts montants
    stopTime_Phase_1 = micros();
    period_Phase_1 = stopTime_Phase_1 - startTime_Phase_1;
    Serial.print("Phase1 : ");
    Serial.println(period_Phase_1);
    phase1_detected = false;
    
    // Calcul de l'angle si la période de Hall est déjà disponible
    if (Period_Hall_1 != 0) {
      detachInterrupt(digitalPinToInterrupt(Phase1));
      detachInterrupt(digitalPinToInterrupt(Hall_PulsePin1));
      calculateAngle();
      period_Phase_1 = 0;
      Period_Hall_1 = 0;
      attachInterrupt(digitalPinToInterrupt(Phase1), countPulse_Phase1, RISING);
      attachInterrupt(digitalPinToInterrupt(Hall_PulsePin1), countPulse_Hall1, RISING);
    }
  }
}

void countPulse_Hall1() {
  if (!hall1_detected) {
    // Première détection de Hall1, mise à jour du timer Hall1
    stopTime_Hall_1 = micros();
    hall1_detected = true;
    Period_Hall_1 = stopTime_Hall_1 - startTime_Hall_1;
    Serial.print("Hall1 : ");
    Serial.println(Period_Hall_1);
    
    // Calcul de l'angle si la période de phase est déjà disponible
    if (period_Phase_1 != 0) {
      detachInterrupt(digitalPinToInterrupt(Phase1));
      detachInterrupt(digitalPinToInterrupt(Hall_PulsePin1));
      calculateAngle();
      period_Phase_1 = 0;
      Period_Hall_1 = 0;
      attachInterrupt(digitalPinToInterrupt(Phase1), countPulse_Phase1, RISING);
      attachInterrupt(digitalPinToInterrupt(Hall_PulsePin1), countPulse_Hall1, RISING);
    }
  } else {
    // Réinitialisation de hall1_detected dès que l'impulsion est traitée
    hall1_detected = false;
  }
}

void calculateAngle() {
  // Calcul de l'angle selon la formule donnée
  float angle = (static_cast<float>(Period_Hall_1) / period_Phase_1) * 360;

  if (angle >= 180) {
    angle = 360 - angle;
    Serial.print("Hall en avance : Angle : ");
  } else {
    Serial.print("Hall en retard : Angle : ");
  }

    Serial.println(angle);

 // Mise à jour des valeurs minimales et maximales
  if (angleCount == 0) {
    minValue = angle;
    maxValue = angle;
  } else {
    if (angle < minValue) {
      minValue = angle;
    }
    if (angle > maxValue) {
      maxValue = angle;
    }
  }

  // Ajouter l'angle à la somme et incrémenter le compteur d'angles
  sumAngles += angle;
  angleCount++;

  if (angleCount == 12) {
    // Calculer la moyenne des angles
    float moyenneAngle = sumAngles / 12;
    Serial.print("Moyenne des angles : ");
    Serial.println(moyenneAngle);
    Serial.print("Valeur minimale : ");
    Serial.println(minValue);
    Serial.print("Valeur maximale : ");
    Serial.println(maxValue);

    // Réinitialiser la somme et le compteur
    sumAngles = 0;
    angleCount = 0;
  }

  // Réinitialisation des périodes pour les prochaines mesures
  period_Phase_1 = 0;
  Period_Hall_1 = 0;
}

Please explain your terms "hall cell" and "fcem". They do not appear in context in your question.

Timers are variable because they are simply counters that will reach a limit (time) as they count clock pulses. You change the count the time changes as the clock remains stable. Start walking and counting, each step is more time added to your walk.

You can also use the 'timers' to count external pulses.

I'm looking for a phase shift, I look at my motor, my phase and my hall cell and when I run my motor the period of my phase is good, 1.3 seconds, but the interruption of my hall cell jumps from one edge to the other, I don't know why and the elapsed time is 2 seconds for the hall cell, but it should be less than my phase.

Take a step back and assume we have no idea about the physical configuration of your setup, the electrical and mechanical connections therein, or what you're trying to accomplish ....... BECAUSE WE DON'T.

So, start over by posting that information (diagrams in addition to textual description) along with complete explanations for your interpretation of all the terms you're using.

1 Like

Functions called by interrupts must be as simple and quick as possible so as not to impede new interrupts.

Your routines called by interrupt are very extensive and time-consuming.

void countPulse_Phase1() {
  if (!phase1_detected) {
    // Première détection de Phase1, démarrage des deux timers
    startTime_Phase_1 = micros();
    startTime_Hall_1 = micros();
    phase1_detected = true;
  } else {
    // Détection suivante de Phase1, calcul de la période entre les fronts montants
    stopTime_Phase_1 = micros();
    period_Phase_1 = stopTime_Phase_1 - startTime_Phase_1;
    Serial.print("Phase1 : ");
    Serial.println(period_Phase_1);
    phase1_detected = false;
    
    // Calcul de l'angle si la période de Hall est déjà disponible
    if (Period_Hall_1 != 0) {
      detachInterrupt(digitalPinToInterrupt(Phase1));
      detachInterrupt(digitalPinToInterrupt(Hall_PulsePin1));
      calculateAngle();
      period_Phase_1 = 0;
      Period_Hall_1 = 0;
      attachInterrupt(digitalPinToInterrupt(Phase1), countPulse_Phase1, RISING);
      attachInterrupt(digitalPinToInterrupt(Hall_PulsePin1), countPulse_Hall1, RISING);
    }
  }
}
void countPulse_Hall1() {
  if (!hall1_detected) {
    // Première détection de Hall1, mise à jour du timer Hall1
    stopTime_Hall_1 = micros();
    hall1_detected = true;
    Period_Hall_1 = stopTime_Hall_1 - startTime_Hall_1;
    Serial.print("Hall1 : ");
    Serial.println(Period_Hall_1);
    
    // Calcul de l'angle si la période de phase est déjà disponible
    if (period_Phase_1 != 0) {
      detachInterrupt(digitalPinToInterrupt(Phase1));
      detachInterrupt(digitalPinToInterrupt(Hall_PulsePin1));
      calculateAngle();
      period_Phase_1 = 0;
      Period_Hall_1 = 0;
      attachInterrupt(digitalPinToInterrupt(Phase1), countPulse_Phase1, RISING);
      attachInterrupt(digitalPinToInterrupt(Hall_PulsePin1), countPulse_Hall1, RISING);
    }
  } else {
    // Réinitialisation de hall1_detected dès que l'impulsion est traitée
    hall1_detected = false;
  }
}
1 Like

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